[Lldb-commits] [lldb] r290117 - Expression evaluation for overloaded C functions (redux)

Luke Drummond via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 19 09:22:44 PST 2016


Author: ldrumm
Date: Mon Dec 19 11:22:44 2016
New Revision: 290117

URL: http://llvm.org/viewvc/llvm-project?rev=290117&view=rev
Log:
Expression evaluation for overloaded C functions (redux)

This is a redux of [Ewan's patch](https://reviews.llvm.org/D17957) , refactored
to properly substitute primitive  types using a hook in the itanium demangler,
and updated after the previous patch went stale

The new `SubsPrimitiveParmItanium` function takes a symbol name and replacement
primitive type parameter as before but parses it using the FastDemangler, which
has been modified to be able to notify clients of parse events (primitive types
at this point).

Additionally, we now use a `set` of `ConstStrings` instead of a `vector` so
that we don't try and resolve the same invalid candidate multiple times.

Differential Revision: https://reviews.llvm.org/D27223
Subscribers: lldb-commits


Modified:
    lldb/trunk/include/lldb/Core/FastDemangle.h
    lldb/trunk/source/Core/FastDemangle.cpp
    lldb/trunk/source/Expression/IRExecutionUnit.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h

Modified: lldb/trunk/include/lldb/Core/FastDemangle.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FastDemangle.h?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FastDemangle.h (original)
+++ lldb/trunk/include/lldb/Core/FastDemangle.h Mon Dec 19 11:22:44 2016
@@ -10,11 +10,17 @@
 #ifndef liblldb_FastDemangle_h_
 #define liblldb_FastDemangle_h_
 
+#include <cstddef>
+
+#include <functional>
+
 namespace lldb_private {
 
 char *FastDemangle(const char *mangled_name);
 
-char *FastDemangle(const char *mangled_name, long mangled_name_length);
+char *
+FastDemangle(const char *mangled_name, size_t mangled_name_length,
+             std::function<void(const char *s)> primitive_type_hook = nullptr);
 }
 
 #endif

Modified: lldb/trunk/source/Core/FastDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FastDemangle.cpp?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/source/Core/FastDemangle.cpp (original)
+++ lldb/trunk/source/Core/FastDemangle.cpp Mon Dec 19 11:22:44 2016
@@ -11,6 +11,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <functional>
+
+#include "lldb/Core/FastDemangle.h"
 #include "lldb/lldb-private.h"
 
 //#define DEBUG_FAILURES 1
@@ -119,7 +122,9 @@ public:
   /// @param storage_size Number of bytes of space available scratch memory
   /// referenced by storage_ptr
 
-  SymbolDemangler(void *storage_ptr, int storage_size) {
+  SymbolDemangler(void *storage_ptr, size_t storage_size,
+                  std::function<void(const char *)> builtins_hook = nullptr)
+      : m_builtins_hook(builtins_hook) {
     // Use up to 1/8th of the provided space for rewrite ranges
     m_rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange);
     m_rewrite_ranges = (BufferRange *)storage_ptr;
@@ -509,6 +514,9 @@ private:
   //                ::= u <source-name>    # vendor extended type
 
   const char *TryParseBuiltinType() {
+    if (m_builtins_hook)
+      m_builtins_hook(m_read_ptr);
+
     switch (*m_read_ptr++) {
     case 'v':
       return "void";
@@ -1150,6 +1158,23 @@ private:
     return RewriteTemplateArg(count + 1);
   }
 
+  // <vector-type>
+  // Dv <dimension number> _ <vector type>
+  bool TryParseVectorType() {
+    const int dimension = TryParseNumber();
+    if (dimension == -1)
+      return false;
+
+    if (*m_read_ptr++ != '_')
+      return false;
+
+    char vec_dimens[32] = {'\0'};
+    ::snprintf(vec_dimens, sizeof vec_dimens - 1, " __vector(%d)", dimension);
+    ParseType();
+    Write(vec_dimens);
+    return true;
+  }
+
   // <type> ::= <builtin-type>
   //        ::= <function-type>
   //        ::= <class-enum-type>
@@ -1191,9 +1216,12 @@ private:
         if (!ParseType())
           return false;
         break;
+      case 'v':
+        if (!TryParseVectorType())
+          return false;
+        break;
       case 'T':
       case 't':
-      case 'v':
       default:
 #ifdef DEBUG_FAILURES
         printf("*** Unsupported type: %.3s\n", failed_type);
@@ -2346,6 +2374,7 @@ private:
   char *m_write_ptr;
   int m_next_template_arg_index;
   int m_next_substitute_index;
+  std::function<void(const char *s)> m_builtins_hook;
 };
 
 } // Anonymous namespace
@@ -2358,9 +2387,10 @@ char *FastDemangle(const char *mangled_n
   return demangler.GetDemangledCopy(mangled_name);
 }
 
-char *FastDemangle(const char *mangled_name, long mangled_name_length) {
+char *FastDemangle(const char *mangled_name, size_t mangled_name_length,
+                   std::function<void(const char *s)> builtins_hook) {
   char buffer[16384];
-  SymbolDemangler demangler(buffer, sizeof(buffer));
+  SymbolDemangler demangler(buffer, sizeof(buffer), builtins_hook);
   return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
 }
 } // lldb_private namespace

Modified: lldb/trunk/source/Expression/IRExecutionUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRExecutionUnit.cpp?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRExecutionUnit.cpp (original)
+++ lldb/trunk/source/Expression/IRExecutionUnit.cpp Mon Dec 19 11:22:44 2016
@@ -776,22 +776,9 @@ void IRExecutionUnit::CollectCandidateCP
       }
     }
 
-    // Maybe we're looking for a const symbol but the debug info told us it was
-    // const...
-    if (!strncmp(name.GetCString(), "_ZN", 3) &&
-        strncmp(name.GetCString(), "_ZNK", 4)) {
-      std::string fixed_scratch("_ZNK");
-      fixed_scratch.append(name.GetCString() + 3);
-      CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
-    }
-
-    // Maybe we're looking for a static symbol but we thought it was global...
-    if (!strncmp(name.GetCString(), "_Z", 2) &&
-        strncmp(name.GetCString(), "_ZL", 3)) {
-      std::string fixed_scratch("_ZL");
-      fixed_scratch.append(name.GetCString() + 2);
-      CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
-    }
+    std::set<ConstString> alternates;
+    CPlusPlusLanguage::FindAlternateFunctionManglings(name, alternates);
+    CPP_specs.insert(CPP_specs.end(), alternates.begin(), alternates.end());
   }
 }
 

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp Mon Dec 19 11:22:44 2016
@@ -1978,11 +1978,12 @@ void ClangExpressionDeclMap::AddOneFunct
   if (function) {
     Type *function_type = function->GetType();
 
-    const lldb::LanguageType comp_unit_language =
-        function->GetCompileUnit()->GetLanguage();
-    const bool extern_c = Language::LanguageIsC(comp_unit_language) ||
-                          (Language::LanguageIsObjC(comp_unit_language) &&
-                           !Language::LanguageIsCPlusPlus(comp_unit_language));
+    const auto lang = function->GetCompileUnit()->GetLanguage();
+    const auto name = function->GetMangled().GetMangledName().AsCString();
+    const bool extern_c = (Language::LanguageIsC(lang) &&
+                           !CPlusPlusLanguage::IsCPPMangledName(name)) ||
+                          (Language::LanguageIsObjC(lang) &&
+                           !Language::LanguageIsCPlusPlus(lang));
 
     if (!extern_c) {
       TypeSystem *type_system = function->GetDeclContext().GetTypeSystem();

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp Mon Dec 19 11:22:44 2016
@@ -10,17 +10,22 @@
 #include "CPlusPlusLanguage.h"
 
 // C Includes
-// C++ Includes
 #include <cctype>
 #include <cstring>
+
+// C++ Includes
 #include <functional>
+#include <memory>
 #include <mutex>
+#include <set>
 
 // Other libraries and framework includes
 #include "llvm/ADT/StringRef.h"
 
 // Project includes
 #include "lldb/Core/ConstString.h"
+#include "lldb/Core/FastDemangle.h"
+#include "lldb/Core/Log.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/UniqueCStringMap.h"
@@ -440,6 +445,101 @@ CPlusPlusLanguage::FindEquivalentNames(C
   return count;
 }
 
+/// Given a mangled function `mangled`, replace all the primitive function type
+/// arguments of `search` with type `replace`.
+static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
+                                            llvm::StringRef search,
+                                            llvm::StringRef replace) {
+  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+  const size_t max_len =
+      mangled.size() + mangled.count(search) * replace.size() + 1;
+
+  // Make a temporary buffer to fix up the mangled parameter types and copy the
+  // original there
+  std::string output_buf;
+  output_buf.reserve(max_len);
+  output_buf.insert(0, mangled.str());
+  ptrdiff_t replaced_offset = 0;
+
+  auto swap_parms_hook = [&](const char *parsee) {
+    if (!parsee || !*parsee)
+      return;
+
+    // Check whether we've found a substitutee
+    llvm::StringRef s(parsee);
+    if (s.startswith(search)) {
+      // account for the case where a replacement is of a different length to
+      // the original
+      replaced_offset += replace.size() - search.size();
+
+      ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
+      output_buf.erase(replace_idx, search.size());
+      output_buf.insert(replace_idx, replace.str());
+    }
+  };
+
+  // FastDemangle will call our hook for each instance of a primitive type,
+  // allowing us to perform substitution
+  const char *const demangled =
+      FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
+
+  if (log)
+    log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
+                mangled.str().c_str(), demangled, output_buf.c_str(),
+                FastDemangle(output_buf.c_str()));
+
+  return output_buf == mangled ? ConstString() : ConstString(output_buf);
+}
+
+uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
+    const ConstString mangled_name, std::set<ConstString> &alternates) {
+  const auto start_size = alternates.size();
+  /// Get a basic set of alternative manglings for the given symbol `name`, by
+  /// making a few basic possible substitutions on basic types, storage duration
+  /// and `const`ness for the given symbol. The output parameter `alternates`
+  /// is filled with a best-guess, non-exhaustive set of different manglings
+  /// for the given name.
+
+  // Maybe we're looking for a const symbol but the debug info told us it was
+  // non-const...
+  if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
+      strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
+    std::string fixed_scratch("_ZNK");
+    fixed_scratch.append(mangled_name.GetCString() + 3);
+    alternates.insert(ConstString(fixed_scratch));
+  }
+
+  // Maybe we're looking for a static symbol but we thought it was global...
+  if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
+      strncmp(mangled_name.GetCString(), "_ZL", 3)) {
+    std::string fixed_scratch("_ZL");
+    fixed_scratch.append(mangled_name.GetCString() + 2);
+    alternates.insert(ConstString(fixed_scratch));
+  }
+
+  // `char` is implementation defined as either `signed` or `unsigned`.  As a
+  // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
+  // char, 'h'-unsigned char.  If we're looking for symbols with a signed char
+  // parameter, try finding matches which have the general case 'c'.
+  if (ConstString char_fixup =
+          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
+    alternates.insert(char_fixup);
+
+  // long long parameter mangling 'x', may actually just be a long 'l' argument
+  if (ConstString long_fixup =
+          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
+    alternates.insert(long_fixup);
+
+  // unsigned long long parameter mangling 'y', may actually just be unsigned
+  // long 'm' argument
+  if (ConstString ulong_fixup =
+          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
+    alternates.insert(ulong_fixup);
+
+  return alternates.size() - start_size;
+}
+
 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   if (!cpp_category_sp)
     return;
@@ -931,7 +1031,7 @@ std::unique_ptr<Language::TypeScavenger>
       return candidate;
     }
   };
-  
+
   return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
 }
 

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h?rev=290117&r1=290116&r2=290117&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h Mon Dec 19 11:22:44 2016
@@ -12,6 +12,7 @@
 
 // C Includes
 // C++ Includes
+#include <set>
 #include <vector>
 
 // Other libraries and framework includes
@@ -93,7 +94,6 @@ public:
   }
 
   std::unique_ptr<TypeScavenger> GetTypeScavenger() override;
-  
   lldb::TypeCategoryImplSP GetFormatters() override;
 
   HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override;
@@ -142,6 +142,12 @@ public:
   static uint32_t FindEquivalentNames(ConstString type_name,
                                       std::vector<ConstString> &equivalents);
 
+  // Given a mangled function name, calculates some alternative manglings since
+  // the compiler mangling may not line up with the symbol we are expecting
+  static uint32_t
+  FindAlternateFunctionManglings(const ConstString mangled,
+                                 std::set<ConstString> &candidates);
+
   //------------------------------------------------------------------
   // PluginInterface protocol
   //------------------------------------------------------------------




More information about the lldb-commits mailing list