diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp | 254 |
1 files changed, 134 insertions, 120 deletions
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp index c502b18555f0..2472580a41d5 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp @@ -10,9 +10,10 @@ #include <map> #include <set> -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" + #include "lldb/Core/Module.h" +#include "lldb/Core/RichManglingContext.h" #include "lldb/Core/STLUtils.h" #include "lldb/Core/Section.h" #include "lldb/Symbol/ObjectFile.h" @@ -23,6 +24,8 @@ #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "llvm/ADT/StringRef.h" + using namespace lldb; using namespace lldb_private; @@ -136,6 +139,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) { } break; } + } else { + s->PutCString("\n"); } } @@ -215,6 +220,40 @@ const Symbol *Symtab::SymbolAtIndex(size_t idx) const { //---------------------------------------------------------------------- // InitNameIndexes //---------------------------------------------------------------------- +static bool lldb_skip_name(llvm::StringRef mangled, + Mangled::ManglingScheme scheme) { + switch (scheme) { + case Mangled::eManglingSchemeItanium: { + if (mangled.size() < 3 || !mangled.startswith("_Z")) + return true; + + // Avoid the following types of symbols in the index. + switch (mangled[2]) { + case 'G': // guard variables + case 'T': // virtual tables, VTT structures, typeinfo structures + names + case 'Z': // named local entities (if we eventually handle + // eSymbolTypeData, we will want this back) + return true; + + default: + break; + } + + // Include this name in the index. + return false; + } + + // No filters for this scheme yet. Include all names in indexing. + case Mangled::eManglingSchemeMSVC: + return false; + + // Don't try and demangle things we can't categorize. + case Mangled::eManglingSchemeNone: + return true; + } + llvm_unreachable("unknown scheme!"); +} + void Symtab::InitNameIndexes() { // Protected function, no need to lock mutex... if (!m_name_indexes_computed) { @@ -243,16 +282,19 @@ void Symtab::InitNameIndexes() { m_name_to_index.Reserve(actual_count); #endif - NameToIndexMap::Entry entry; - - // The "const char *" in "class_contexts" must come from a - // ConstString::GetCString() + // The "const char *" in "class_contexts" and backlog::value_type::second + // must come from a ConstString::GetCString() std::set<const char *> class_contexts; - UniqueCStringMap<uint32_t> mangled_name_to_index; - std::vector<const char *> symbol_contexts(num_symbols, nullptr); + std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog; + backlog.reserve(num_symbols / 2); + + // Instantiation of the demangler is expensive, so better use a single one + // for all entries during batch processing. + RichManglingContext rmc; + NameToIndexMap::Entry entry; for (entry.value = 0; entry.value < num_symbols; ++entry.value) { - const Symbol *symbol = &m_symbols[entry.value]; + Symbol *symbol = &m_symbols[entry.value]; // Don't let trampolines get into the lookup by name map If we ever need // the trampoline symbols to be searchable by name we can remove this and @@ -261,7 +303,9 @@ void Symtab::InitNameIndexes() { if (symbol->IsTrampoline()) continue; - const Mangled &mangled = symbol->GetMangled(); + // If the symbol's name string matched a Mangled::ManglingScheme, it is + // stored in the mangled field. + Mangled &mangled = symbol->GetMangled(); entry.cstring = mangled.GetMangledName(); if (entry.cstring) { m_name_to_index.Append(entry); @@ -274,70 +318,15 @@ void Symtab::InitNameIndexes() { m_name_to_index.Append(entry); } - const SymbolType symbol_type = symbol->GetType(); - if (symbol_type == eSymbolTypeCode || - symbol_type == eSymbolTypeResolver) { - llvm::StringRef entry_ref(entry.cstring.GetStringRef()); - if (entry_ref[0] == '_' && entry_ref[1] == 'Z' && - (entry_ref[2] != 'T' && // avoid virtual table, VTT structure, - // typeinfo structure, and typeinfo - // name - entry_ref[2] != 'G' && // avoid guard variables - entry_ref[2] != 'Z')) // named local entities (if we - // eventually handle eSymbolTypeData, - // we will want this back) - { - CPlusPlusLanguage::MethodName cxx_method( - mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus)); - entry.cstring = ConstString(cxx_method.GetBasename()); - if (entry.cstring) { - // ConstString objects permanently store the string in the pool - // so calling GetCString() on the value gets us a const char * - // that will never go away - const char *const_context = - ConstString(cxx_method.GetContext()).GetCString(); - - if (!const_context || const_context[0] == 0) { - // No context for this function so this has to be a basename - m_basename_to_index.Append(entry); - // If there is no context (no namespaces or class scopes that - // come before the function name) then this also could be a - // fullname. - m_name_to_index.Append(entry); - } else { - entry_ref = entry.cstring.GetStringRef(); - if (entry_ref[0] == '~' || - !cxx_method.GetQualifiers().empty()) { - // The first character of the demangled basename is '~' which - // means we have a class destructor. We can use this - // information to help us know what is a class and what - // isn't. - if (class_contexts.find(const_context) == class_contexts.end()) - class_contexts.insert(const_context); - m_method_to_index.Append(entry); - } else { - if (class_contexts.find(const_context) != - class_contexts.end()) { - // The current decl context is in our "class_contexts" - // which means this is a method on a class - m_method_to_index.Append(entry); - } else { - // We don't know if this is a function basename or a - // method, so put it into a temporary collection so once we - // are done we can look in class_contexts to see if each - // entry is a class or just a function and will put any - // remaining items into m_method_to_index or - // m_basename_to_index as needed - mangled_name_to_index.Append(entry); - symbol_contexts[entry.value] = const_context; - } - } - } - } - } + const SymbolType type = symbol->GetType(); + if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { + if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name)) + RegisterMangledNameEntry(entry, class_contexts, backlog, rmc); } } + // Symbol name strings that didn't match a Mangled::ManglingScheme, are + // stored in the demangled field. entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()); if (entry.cstring) { m_name_to_index.Append(entry); @@ -367,25 +356,10 @@ void Symtab::InitNameIndexes() { } } - size_t count; - if (!mangled_name_to_index.IsEmpty()) { - count = mangled_name_to_index.GetSize(); - for (size_t i = 0; i < count; ++i) { - if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) { - entry.cstring = mangled_name_to_index.GetCStringAtIndex(i); - if (symbol_contexts[entry.value] && - class_contexts.find(symbol_contexts[entry.value]) != - class_contexts.end()) { - m_method_to_index.Append(entry); - } else { - // If we got here, we have something that had a context (was inside - // a namespace or class) yet we don't know if the entry - m_method_to_index.Append(entry); - m_basename_to_index.Append(entry); - } - } - } + for (const auto &record : backlog) { + RegisterBacklogEntry(record.first, record.second, class_contexts); } + m_name_to_index.Sort(); m_name_to_index.SizeToFit(); m_selector_to_index.Sort(); @@ -397,6 +371,71 @@ void Symtab::InitNameIndexes() { } } +void Symtab::RegisterMangledNameEntry( + NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts, + std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, + RichManglingContext &rmc) { + // Only register functions that have a base name. + rmc.ParseFunctionBaseName(); + llvm::StringRef base_name = rmc.GetBufferRef(); + if (base_name.empty()) + return; + + // The base name will be our entry's name. + entry.cstring = ConstString(base_name); + + rmc.ParseFunctionDeclContextName(); + llvm::StringRef decl_context = rmc.GetBufferRef(); + + // Register functions with no context. + if (decl_context.empty()) { + // This has to be a basename + m_basename_to_index.Append(entry); + // If there is no context (no namespaces or class scopes that come before + // the function name) then this also could be a fullname. + m_name_to_index.Append(entry); + return; + } + + // Make sure we have a pool-string pointer and see if we already know the + // context name. + const char *decl_context_ccstr = ConstString(decl_context).GetCString(); + auto it = class_contexts.find(decl_context_ccstr); + + // Register constructors and destructors. They are methods and create + // declaration contexts. + if (rmc.IsCtorOrDtor()) { + m_method_to_index.Append(entry); + if (it == class_contexts.end()) + class_contexts.insert(it, decl_context_ccstr); + return; + } + + // Register regular methods with a known declaration context. + if (it != class_contexts.end()) { + m_method_to_index.Append(entry); + return; + } + + // Regular methods in unknown declaration contexts are put to the backlog. We + // will revisit them once we processed all remaining symbols. + backlog.push_back(std::make_pair(entry, decl_context_ccstr)); +} + +void Symtab::RegisterBacklogEntry( + const NameToIndexMap::Entry &entry, const char *decl_context, + const std::set<const char *> &class_contexts) { + auto it = class_contexts.find(decl_context); + if (it != class_contexts.end()) { + m_method_to_index.Append(entry); + } else { + // If we got here, we have something that had a context (was inside + // a namespace or class) yet we don't know the entry + m_method_to_index.Append(entry); + m_basename_to_index.Append(entry); + } +} + void Symtab::PreloadSymbols() { std::lock_guard<std::recursive_mutex> guard(m_mutex); InitNameIndexes(); @@ -571,10 +610,9 @@ void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, return; // Sort the indexes in place using std::stable_sort. - // NOTE: The use of std::stable_sort instead of std::sort here is strictly for - // performance, - // not correctness. The indexes vector tends to be "close" to sorted, which - // the stable sort handles better. + // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly + // for performance, not correctness. The indexes vector tends to be "close" + // to sorted, which the stable sort handles better. std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); @@ -701,7 +739,7 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( for (uint32_t i = 0; i < sym_end; i++) { if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) { - if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) + if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) continue; const char *name = m_symbols[i].GetName().AsCString(); @@ -937,32 +975,8 @@ void Symtab::InitAddressIndexes() { void Symtab::CalculateSymbolSizes() { std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (!m_symbols.empty()) { - if (!m_file_addr_to_index_computed) - InitAddressIndexes(); - - const size_t num_entries = m_file_addr_to_index.GetSize(); - - for (size_t i = 0; i < num_entries; ++i) { - // The entries in the m_file_addr_to_index have calculated the sizes - // already so we will use this size if we need to. - const FileRangeToIndexMap::Entry &entry = - m_file_addr_to_index.GetEntryRef(i); - - Symbol &symbol = m_symbols[entry.data]; - - // If the symbol size is already valid, no need to do anything - if (symbol.GetByteSizeIsValid()) - continue; - - const addr_t range_size = entry.GetByteSize(); - if (range_size > 0) { - symbol.SetByteSize(range_size); - symbol.SetSizeIsSynthesized(true); - } - } - } + // Size computation happens inside InitAddressIndexes. + InitAddressIndexes(); } Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { @@ -1117,7 +1131,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name, } if (!symbol_indexes.empty()) { - std::sort(symbol_indexes.begin(), symbol_indexes.end()); + llvm::sort(symbol_indexes.begin(), symbol_indexes.end()); symbol_indexes.erase( std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end()); |
