diff options
-rw-r--r-- | lldb/include/lldb/Core/FastDemangle.h | 8 | ||||
-rw-r--r-- | lldb/source/Core/FastDemangle.cpp | 38 | ||||
-rw-r--r-- | lldb/source/Expression/IRExecutionUnit.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp | 11 | ||||
-rw-r--r-- | lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp | 104 | ||||
-rw-r--r-- | lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h | 8 |
6 files changed, 159 insertions, 29 deletions
diff --git a/lldb/include/lldb/Core/FastDemangle.h b/lldb/include/lldb/Core/FastDemangle.h index 1a8b8adb857..f779aaa0460 100644 --- a/lldb/include/lldb/Core/FastDemangle.h +++ b/lldb/include/lldb/Core/FastDemangle.h @@ -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 diff --git a/lldb/source/Core/FastDemangle.cpp b/lldb/source/Core/FastDemangle.cpp index 00a158a46c1..0bed4a1f20a 100644 --- a/lldb/source/Core/FastDemangle.cpp +++ b/lldb/source/Core/FastDemangle.cpp @@ -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_name) { 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 diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 9ad2b33ce71..f18d96bd9e2 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -776,22 +776,9 @@ void IRExecutionUnit::CollectCandidateCPlusPlusNames( } } - // 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()); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 3fa78f01f51..c1470c5aeb2 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1978,11 +1978,12 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, 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(); diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index fc70948d3a8..b5527edacd1 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -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(ConstString type_name, 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> CPlusPlusLanguage::GetTypeScavenger() { return candidate; } }; - + return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger()); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index af60957cf63..be5cbae57de 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -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 //------------------------------------------------------------------ |