summaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp254
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());