15ffd83dbSDimitry Andric //===-- Symtab.cpp --------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include <map> 100b57cec5SDimitry Andric #include <set> 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Core/Module.h" 130b57cec5SDimitry Andric #include "lldb/Core/RichManglingContext.h" 140b57cec5SDimitry Andric #include "lldb/Core/Section.h" 150b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 160b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h" 170b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/Symtab.h" 19*fe6060f1SDimitry Andric #include "lldb/Target/Language.h" 200b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h" 210b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace lldb; 270b57cec5SDimitry Andric using namespace lldb_private; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric Symtab::Symtab(ObjectFile *objfile) 30480093f4SDimitry Andric : m_objfile(objfile), m_symbols(), m_file_addr_to_index(*this), 31*fe6060f1SDimitry Andric m_name_to_symbol_indices(), m_mutex(), 32*fe6060f1SDimitry Andric m_file_addr_to_index_computed(false), m_name_indexes_computed(false) { 33*fe6060f1SDimitry Andric m_name_to_symbol_indices.emplace(std::make_pair( 34*fe6060f1SDimitry Andric lldb::eFunctionNameTypeNone, UniqueCStringMap<uint32_t>())); 35*fe6060f1SDimitry Andric m_name_to_symbol_indices.emplace(std::make_pair( 36*fe6060f1SDimitry Andric lldb::eFunctionNameTypeBase, UniqueCStringMap<uint32_t>())); 37*fe6060f1SDimitry Andric m_name_to_symbol_indices.emplace(std::make_pair( 38*fe6060f1SDimitry Andric lldb::eFunctionNameTypeMethod, UniqueCStringMap<uint32_t>())); 39*fe6060f1SDimitry Andric m_name_to_symbol_indices.emplace(std::make_pair( 40*fe6060f1SDimitry Andric lldb::eFunctionNameTypeSelector, UniqueCStringMap<uint32_t>())); 41*fe6060f1SDimitry Andric } 420b57cec5SDimitry Andric 43*fe6060f1SDimitry Andric Symtab::~Symtab() = default; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void Symtab::Reserve(size_t count) { 460b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 470b57cec5SDimitry Andric // when calling this function to avoid performance issues. 480b57cec5SDimitry Andric m_symbols.reserve(count); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric Symbol *Symtab::Resize(size_t count) { 520b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 530b57cec5SDimitry Andric // when calling this function to avoid performance issues. 540b57cec5SDimitry Andric m_symbols.resize(count); 550b57cec5SDimitry Andric return m_symbols.empty() ? nullptr : &m_symbols[0]; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric uint32_t Symtab::AddSymbol(const Symbol &symbol) { 590b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 600b57cec5SDimitry Andric // when calling this function to avoid performance issues. 610b57cec5SDimitry Andric uint32_t symbol_idx = m_symbols.size(); 62*fe6060f1SDimitry Andric auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone); 63*fe6060f1SDimitry Andric name_to_index.Clear(); 640b57cec5SDimitry Andric m_file_addr_to_index.Clear(); 650b57cec5SDimitry Andric m_symbols.push_back(symbol); 660b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 670b57cec5SDimitry Andric m_name_indexes_computed = false; 680b57cec5SDimitry Andric return symbol_idx; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric size_t Symtab::GetNumSymbols() const { 720b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 730b57cec5SDimitry Andric return m_symbols.size(); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void Symtab::SectionFileAddressesChanged() { 77*fe6060f1SDimitry Andric auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone); 78*fe6060f1SDimitry Andric name_to_index.Clear(); 790b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 82480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order, 83480093f4SDimitry Andric Mangled::NamePreference name_preference) { 840b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 870b57cec5SDimitry Andric s->Indent(); 880b57cec5SDimitry Andric const FileSpec &file_spec = m_objfile->GetFileSpec(); 890b57cec5SDimitry Andric const char *object_name = nullptr; 900b57cec5SDimitry Andric if (m_objfile->GetModule()) 910b57cec5SDimitry Andric object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric if (file_spec) 940b57cec5SDimitry Andric s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, 950b57cec5SDimitry Andric file_spec.GetPath().c_str(), object_name ? "(" : "", 960b57cec5SDimitry Andric object_name ? object_name : "", object_name ? ")" : "", 970b57cec5SDimitry Andric (uint64_t)m_symbols.size()); 980b57cec5SDimitry Andric else 990b57cec5SDimitry Andric s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (!m_symbols.empty()) { 1020b57cec5SDimitry Andric switch (sort_order) { 1030b57cec5SDimitry Andric case eSortOrderNone: { 1040b57cec5SDimitry Andric s->PutCString(":\n"); 1050b57cec5SDimitry Andric DumpSymbolHeader(s); 1060b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 1070b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 1080b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 1090b57cec5SDimitry Andric s->Indent(); 110480093f4SDimitry Andric pos->Dump(s, target, std::distance(begin, pos), name_preference); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric } break; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric case eSortOrderByName: { 1150b57cec5SDimitry Andric // Although we maintain a lookup by exact name map, the table isn't 1160b57cec5SDimitry Andric // sorted by name. So we must make the ordered symbol list up ourselves. 1170b57cec5SDimitry Andric s->PutCString(" (sorted by name):\n"); 1180b57cec5SDimitry Andric DumpSymbolHeader(s); 119480093f4SDimitry Andric 120480093f4SDimitry Andric std::multimap<llvm::StringRef, const Symbol *> name_map; 1210b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 1220b57cec5SDimitry Andric pos != end; ++pos) { 1230b57cec5SDimitry Andric const char *name = pos->GetName().AsCString(); 1240b57cec5SDimitry Andric if (name && name[0]) 1250b57cec5SDimitry Andric name_map.insert(std::make_pair(name, &(*pos))); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 128480093f4SDimitry Andric for (const auto &name_to_symbol : name_map) { 129480093f4SDimitry Andric const Symbol *symbol = name_to_symbol.second; 1300b57cec5SDimitry Andric s->Indent(); 131480093f4SDimitry Andric symbol->Dump(s, target, symbol - &m_symbols[0], name_preference); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric } break; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric case eSortOrderByAddress: 1360b57cec5SDimitry Andric s->PutCString(" (sorted by address):\n"); 1370b57cec5SDimitry Andric DumpSymbolHeader(s); 1380b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 1390b57cec5SDimitry Andric InitAddressIndexes(); 1400b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 1410b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; ++i) { 1420b57cec5SDimitry Andric s->Indent(); 1430b57cec5SDimitry Andric const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; 144480093f4SDimitry Andric m_symbols[symbol_idx].Dump(s, target, symbol_idx, name_preference); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric break; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric } else { 1490b57cec5SDimitry Andric s->PutCString("\n"); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 153480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes, 154480093f4SDimitry Andric Mangled::NamePreference name_preference) const { 1550b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric const size_t num_symbols = GetNumSymbols(); 1580b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 1590b57cec5SDimitry Andric s->Indent(); 1600b57cec5SDimitry Andric s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", 1610b57cec5SDimitry Andric (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); 1620b57cec5SDimitry Andric s->IndentMore(); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric if (!indexes.empty()) { 1650b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos; 1660b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator end = indexes.end(); 1670b57cec5SDimitry Andric DumpSymbolHeader(s); 1680b57cec5SDimitry Andric for (pos = indexes.begin(); pos != end; ++pos) { 1690b57cec5SDimitry Andric size_t idx = *pos; 1700b57cec5SDimitry Andric if (idx < num_symbols) { 1710b57cec5SDimitry Andric s->Indent(); 172480093f4SDimitry Andric m_symbols[idx].Dump(s, target, idx, name_preference); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric s->IndentLess(); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric void Symtab::DumpSymbolHeader(Stream *s) { 1800b57cec5SDimitry Andric s->Indent(" Debug symbol\n"); 1810b57cec5SDimitry Andric s->Indent(" |Synthetic symbol\n"); 1820b57cec5SDimitry Andric s->Indent(" ||Externally Visible\n"); 1830b57cec5SDimitry Andric s->Indent(" |||\n"); 1840b57cec5SDimitry Andric s->Indent("Index UserID DSX Type File Address/Value Load " 1850b57cec5SDimitry Andric "Address Size Flags Name\n"); 1860b57cec5SDimitry Andric s->Indent("------- ------ --- --------------- ------------------ " 1870b57cec5SDimitry Andric "------------------ ------------------ ---------- " 1880b57cec5SDimitry Andric "----------------------------------\n"); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric static int CompareSymbolID(const void *key, const void *p) { 1920b57cec5SDimitry Andric const user_id_t match_uid = *(const user_id_t *)key; 1930b57cec5SDimitry Andric const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); 1940b57cec5SDimitry Andric if (match_uid < symbol_uid) 1950b57cec5SDimitry Andric return -1; 1960b57cec5SDimitry Andric if (match_uid > symbol_uid) 1970b57cec5SDimitry Andric return 1; 1980b57cec5SDimitry Andric return 0; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const { 2020b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric Symbol *symbol = 2050b57cec5SDimitry Andric (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(), 2060b57cec5SDimitry Andric sizeof(m_symbols[0]), CompareSymbolID); 2070b57cec5SDimitry Andric return symbol; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric Symbol *Symtab::SymbolAtIndex(size_t idx) { 2110b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 2120b57cec5SDimitry Andric // when calling this function to avoid performance issues. 2130b57cec5SDimitry Andric if (idx < m_symbols.size()) 2140b57cec5SDimitry Andric return &m_symbols[idx]; 2150b57cec5SDimitry Andric return nullptr; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric const Symbol *Symtab::SymbolAtIndex(size_t idx) const { 2190b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 2200b57cec5SDimitry Andric // when calling this function to avoid performance issues. 2210b57cec5SDimitry Andric if (idx < m_symbols.size()) 2220b57cec5SDimitry Andric return &m_symbols[idx]; 2230b57cec5SDimitry Andric return nullptr; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric static bool lldb_skip_name(llvm::StringRef mangled, 2270b57cec5SDimitry Andric Mangled::ManglingScheme scheme) { 2280b57cec5SDimitry Andric switch (scheme) { 2290b57cec5SDimitry Andric case Mangled::eManglingSchemeItanium: { 2300b57cec5SDimitry Andric if (mangled.size() < 3 || !mangled.startswith("_Z")) 2310b57cec5SDimitry Andric return true; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // Avoid the following types of symbols in the index. 2340b57cec5SDimitry Andric switch (mangled[2]) { 2350b57cec5SDimitry Andric case 'G': // guard variables 2360b57cec5SDimitry Andric case 'T': // virtual tables, VTT structures, typeinfo structures + names 2370b57cec5SDimitry Andric case 'Z': // named local entities (if we eventually handle 2380b57cec5SDimitry Andric // eSymbolTypeData, we will want this back) 2390b57cec5SDimitry Andric return true; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric default: 2420b57cec5SDimitry Andric break; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // Include this name in the index. 2460b57cec5SDimitry Andric return false; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric // No filters for this scheme yet. Include all names in indexing. 2500b57cec5SDimitry Andric case Mangled::eManglingSchemeMSVC: 2510b57cec5SDimitry Andric return false; 2520b57cec5SDimitry Andric 253*fe6060f1SDimitry Andric // No filters for this scheme yet. Include all names in indexing. 254*fe6060f1SDimitry Andric case Mangled::eManglingSchemeRustV0: 255*fe6060f1SDimitry Andric return false; 256*fe6060f1SDimitry Andric 2570b57cec5SDimitry Andric // Don't try and demangle things we can't categorize. 2580b57cec5SDimitry Andric case Mangled::eManglingSchemeNone: 2590b57cec5SDimitry Andric return true; 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric llvm_unreachable("unknown scheme!"); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric void Symtab::InitNameIndexes() { 2650b57cec5SDimitry Andric // Protected function, no need to lock mutex... 2660b57cec5SDimitry Andric if (!m_name_indexes_computed) { 2670b57cec5SDimitry Andric m_name_indexes_computed = true; 268e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 269*fe6060f1SDimitry Andric 270*fe6060f1SDimitry Andric // Collect all loaded language plugins. 271*fe6060f1SDimitry Andric std::vector<Language *> languages; 272*fe6060f1SDimitry Andric Language::ForEach([&languages](Language *l) { 273*fe6060f1SDimitry Andric languages.push_back(l); 274*fe6060f1SDimitry Andric return true; 275*fe6060f1SDimitry Andric }); 276*fe6060f1SDimitry Andric 277*fe6060f1SDimitry Andric auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone); 278*fe6060f1SDimitry Andric auto &basename_to_index = 279*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase); 280*fe6060f1SDimitry Andric auto &method_to_index = 281*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod); 282*fe6060f1SDimitry Andric auto &selector_to_index = 283*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeSelector); 2840b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 2850b57cec5SDimitry Andric const size_t num_symbols = m_symbols.size(); 286*fe6060f1SDimitry Andric name_to_index.Reserve(num_symbols); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // The "const char *" in "class_contexts" and backlog::value_type::second 2890b57cec5SDimitry Andric // must come from a ConstString::GetCString() 2900b57cec5SDimitry Andric std::set<const char *> class_contexts; 2910b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog; 2920b57cec5SDimitry Andric backlog.reserve(num_symbols / 2); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // Instantiation of the demangler is expensive, so better use a single one 2950b57cec5SDimitry Andric // for all entries during batch processing. 2960b57cec5SDimitry Andric RichManglingContext rmc; 2970b57cec5SDimitry Andric for (uint32_t value = 0; value < num_symbols; ++value) { 2980b57cec5SDimitry Andric Symbol *symbol = &m_symbols[value]; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Don't let trampolines get into the lookup by name map If we ever need 3010b57cec5SDimitry Andric // the trampoline symbols to be searchable by name we can remove this and 3020b57cec5SDimitry Andric // then possibly add a new bool to any of the Symtab functions that 303*fe6060f1SDimitry Andric // lookup symbols by name to indicate if they want trampolines. We also 304*fe6060f1SDimitry Andric // don't want any synthetic symbols with auto generated names in the 305*fe6060f1SDimitry Andric // name lookups. 306*fe6060f1SDimitry Andric if (symbol->IsTrampoline() || symbol->IsSyntheticWithAutoGeneratedName()) 3070b57cec5SDimitry Andric continue; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric // If the symbol's name string matched a Mangled::ManglingScheme, it is 3100b57cec5SDimitry Andric // stored in the mangled field. 3110b57cec5SDimitry Andric Mangled &mangled = symbol->GetMangled(); 3120b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) { 313*fe6060f1SDimitry Andric name_to_index.Append(name, value); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 3160b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 3170b57cec5SDimitry Andric // the annotations. 3180b57cec5SDimitry Andric ConstString stripped = ConstString( 3190b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 320*fe6060f1SDimitry Andric name_to_index.Append(stripped, value); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric const SymbolType type = symbol->GetType(); 3240b57cec5SDimitry Andric if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { 3250b57cec5SDimitry Andric if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name)) 3260b57cec5SDimitry Andric RegisterMangledNameEntry(value, class_contexts, backlog, rmc); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Symbol name strings that didn't match a Mangled::ManglingScheme, are 3310b57cec5SDimitry Andric // stored in the demangled field. 3325ffd83dbSDimitry Andric if (ConstString name = mangled.GetDemangledName()) { 333*fe6060f1SDimitry Andric name_to_index.Append(name, value); 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 3360b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 3370b57cec5SDimitry Andric // the annotations. 3380b57cec5SDimitry Andric name = ConstString( 3390b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 340*fe6060f1SDimitry Andric name_to_index.Append(name, value); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // If the demangled name turns out to be an ObjC name, and is a category 3440b57cec5SDimitry Andric // name, add the version without categories to the index too. 345*fe6060f1SDimitry Andric for (Language *lang : languages) { 346*fe6060f1SDimitry Andric for (auto variant : lang->GetMethodNameVariants(name)) { 347*fe6060f1SDimitry Andric if (variant.GetType() & lldb::eFunctionNameTypeSelector) 348*fe6060f1SDimitry Andric selector_to_index.Append(variant.GetName(), value); 349*fe6060f1SDimitry Andric else if (variant.GetType() & lldb::eFunctionNameTypeFull) 350*fe6060f1SDimitry Andric name_to_index.Append(variant.GetName(), value); 351*fe6060f1SDimitry Andric else if (variant.GetType() & lldb::eFunctionNameTypeMethod) 352*fe6060f1SDimitry Andric method_to_index.Append(variant.GetName(), value); 353*fe6060f1SDimitry Andric else if (variant.GetType() & lldb::eFunctionNameTypeBase) 354*fe6060f1SDimitry Andric basename_to_index.Append(variant.GetName(), value); 355*fe6060f1SDimitry Andric } 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric for (const auto &record : backlog) { 3610b57cec5SDimitry Andric RegisterBacklogEntry(record.first, record.second, class_contexts); 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 364*fe6060f1SDimitry Andric name_to_index.Sort(); 365*fe6060f1SDimitry Andric name_to_index.SizeToFit(); 366*fe6060f1SDimitry Andric selector_to_index.Sort(); 367*fe6060f1SDimitry Andric selector_to_index.SizeToFit(); 368*fe6060f1SDimitry Andric basename_to_index.Sort(); 369*fe6060f1SDimitry Andric basename_to_index.SizeToFit(); 370*fe6060f1SDimitry Andric method_to_index.Sort(); 371*fe6060f1SDimitry Andric method_to_index.SizeToFit(); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric void Symtab::RegisterMangledNameEntry( 3760b57cec5SDimitry Andric uint32_t value, std::set<const char *> &class_contexts, 3770b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, 3780b57cec5SDimitry Andric RichManglingContext &rmc) { 3790b57cec5SDimitry Andric // Only register functions that have a base name. 3800b57cec5SDimitry Andric rmc.ParseFunctionBaseName(); 3810b57cec5SDimitry Andric llvm::StringRef base_name = rmc.GetBufferRef(); 3820b57cec5SDimitry Andric if (base_name.empty()) 3830b57cec5SDimitry Andric return; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // The base name will be our entry's name. 3860b57cec5SDimitry Andric NameToIndexMap::Entry entry(ConstString(base_name), value); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric rmc.ParseFunctionDeclContextName(); 3890b57cec5SDimitry Andric llvm::StringRef decl_context = rmc.GetBufferRef(); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric // Register functions with no context. 3920b57cec5SDimitry Andric if (decl_context.empty()) { 3930b57cec5SDimitry Andric // This has to be a basename 394*fe6060f1SDimitry Andric auto &basename_to_index = 395*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase); 396*fe6060f1SDimitry Andric basename_to_index.Append(entry); 3970b57cec5SDimitry Andric // If there is no context (no namespaces or class scopes that come before 3980b57cec5SDimitry Andric // the function name) then this also could be a fullname. 399*fe6060f1SDimitry Andric auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone); 400*fe6060f1SDimitry Andric name_to_index.Append(entry); 4010b57cec5SDimitry Andric return; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // Make sure we have a pool-string pointer and see if we already know the 4050b57cec5SDimitry Andric // context name. 4060b57cec5SDimitry Andric const char *decl_context_ccstr = ConstString(decl_context).GetCString(); 4070b57cec5SDimitry Andric auto it = class_contexts.find(decl_context_ccstr); 4080b57cec5SDimitry Andric 409*fe6060f1SDimitry Andric auto &method_to_index = 410*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod); 4110b57cec5SDimitry Andric // Register constructors and destructors. They are methods and create 4120b57cec5SDimitry Andric // declaration contexts. 4130b57cec5SDimitry Andric if (rmc.IsCtorOrDtor()) { 414*fe6060f1SDimitry Andric method_to_index.Append(entry); 4150b57cec5SDimitry Andric if (it == class_contexts.end()) 4160b57cec5SDimitry Andric class_contexts.insert(it, decl_context_ccstr); 4170b57cec5SDimitry Andric return; 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric // Register regular methods with a known declaration context. 4210b57cec5SDimitry Andric if (it != class_contexts.end()) { 422*fe6060f1SDimitry Andric method_to_index.Append(entry); 4230b57cec5SDimitry Andric return; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // Regular methods in unknown declaration contexts are put to the backlog. We 4270b57cec5SDimitry Andric // will revisit them once we processed all remaining symbols. 4280b57cec5SDimitry Andric backlog.push_back(std::make_pair(entry, decl_context_ccstr)); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric void Symtab::RegisterBacklogEntry( 4320b57cec5SDimitry Andric const NameToIndexMap::Entry &entry, const char *decl_context, 4330b57cec5SDimitry Andric const std::set<const char *> &class_contexts) { 434*fe6060f1SDimitry Andric auto &method_to_index = 435*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod); 4360b57cec5SDimitry Andric auto it = class_contexts.find(decl_context); 4370b57cec5SDimitry Andric if (it != class_contexts.end()) { 438*fe6060f1SDimitry Andric method_to_index.Append(entry); 4390b57cec5SDimitry Andric } else { 4400b57cec5SDimitry Andric // If we got here, we have something that had a context (was inside 4410b57cec5SDimitry Andric // a namespace or class) yet we don't know the entry 442*fe6060f1SDimitry Andric method_to_index.Append(entry); 443*fe6060f1SDimitry Andric auto &basename_to_index = 444*fe6060f1SDimitry Andric GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase); 445*fe6060f1SDimitry Andric basename_to_index.Append(entry); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric void Symtab::PreloadSymbols() { 4500b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4510b57cec5SDimitry Andric InitNameIndexes(); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, 4550b57cec5SDimitry Andric bool add_demangled, bool add_mangled, 4560b57cec5SDimitry Andric NameToIndexMap &name_to_index_map) const { 457e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 4580b57cec5SDimitry Andric if (add_demangled || add_mangled) { 4590b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 4620b57cec5SDimitry Andric const size_t num_indexes = indexes.size(); 4630b57cec5SDimitry Andric for (size_t i = 0; i < num_indexes; ++i) { 4640b57cec5SDimitry Andric uint32_t value = indexes[i]; 4650b57cec5SDimitry Andric assert(i < m_symbols.size()); 4660b57cec5SDimitry Andric const Symbol *symbol = &m_symbols[value]; 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric const Mangled &mangled = symbol->GetMangled(); 4690b57cec5SDimitry Andric if (add_demangled) { 4705ffd83dbSDimitry Andric if (ConstString name = mangled.GetDemangledName()) 4710b57cec5SDimitry Andric name_to_index_map.Append(name, value); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric if (add_mangled) { 4750b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) 4760b57cec5SDimitry Andric name_to_index_map.Append(name, value); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 4830b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 4840b57cec5SDimitry Andric uint32_t start_idx, 4850b57cec5SDimitry Andric uint32_t end_index) const { 4860b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 4930b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 4940b57cec5SDimitry Andric indexes.push_back(i); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric return indexes.size() - prev_size; 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue( 5010b57cec5SDimitry Andric SymbolType symbol_type, uint32_t flags_value, 5020b57cec5SDimitry Andric std::vector<uint32_t> &indexes, uint32_t start_idx, 5030b57cec5SDimitry Andric uint32_t end_index) const { 5040b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 5110b57cec5SDimitry Andric if ((symbol_type == eSymbolTypeAny || 5120b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) && 5130b57cec5SDimitry Andric m_symbols[i].GetFlags() == flags_value) 5140b57cec5SDimitry Andric indexes.push_back(i); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric return indexes.size() - prev_size; 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 5210b57cec5SDimitry Andric Debug symbol_debug_type, 5220b57cec5SDimitry Andric Visibility symbol_visibility, 5230b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 5240b57cec5SDimitry Andric uint32_t start_idx, 5250b57cec5SDimitry Andric uint32_t end_index) const { 5260b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 5330b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 5340b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 5350b57cec5SDimitry Andric if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 5360b57cec5SDimitry Andric indexes.push_back(i); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric return indexes.size() - prev_size; 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const { 5440b57cec5SDimitry Andric if (!m_symbols.empty()) { 5450b57cec5SDimitry Andric const Symbol *first_symbol = &m_symbols[0]; 5460b57cec5SDimitry Andric if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 5470b57cec5SDimitry Andric return symbol - first_symbol; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric return UINT32_MAX; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric struct SymbolSortInfo { 5530b57cec5SDimitry Andric const bool sort_by_load_addr; 5540b57cec5SDimitry Andric const Symbol *symbols; 5550b57cec5SDimitry Andric }; 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric namespace { 5580b57cec5SDimitry Andric struct SymbolIndexComparator { 5590b57cec5SDimitry Andric const std::vector<Symbol> &symbols; 5600b57cec5SDimitry Andric std::vector<lldb::addr_t> &addr_cache; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // Getting from the symbol to the Address to the File Address involves some 5630b57cec5SDimitry Andric // work. Since there are potentially many symbols here, and we're using this 5640b57cec5SDimitry Andric // for sorting so we're going to be computing the address many times, cache 5650b57cec5SDimitry Andric // that in addr_cache. The array passed in has to be the same size as the 5660b57cec5SDimitry Andric // symbols array passed into the member variable symbols, and should be 5670b57cec5SDimitry Andric // initialized with LLDB_INVALID_ADDRESS. 5680b57cec5SDimitry Andric // NOTE: You have to make addr_cache externally and pass it in because 5690b57cec5SDimitry Andric // std::stable_sort 5700b57cec5SDimitry Andric // makes copies of the comparator it is initially passed in, and you end up 5710b57cec5SDimitry Andric // spending huge amounts of time copying this array... 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric SymbolIndexComparator(const std::vector<Symbol> &s, 5740b57cec5SDimitry Andric std::vector<lldb::addr_t> &a) 5750b57cec5SDimitry Andric : symbols(s), addr_cache(a) { 5760b57cec5SDimitry Andric assert(symbols.size() == addr_cache.size()); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric bool operator()(uint32_t index_a, uint32_t index_b) { 5790b57cec5SDimitry Andric addr_t value_a = addr_cache[index_a]; 5800b57cec5SDimitry Andric if (value_a == LLDB_INVALID_ADDRESS) { 5810b57cec5SDimitry Andric value_a = symbols[index_a].GetAddressRef().GetFileAddress(); 5820b57cec5SDimitry Andric addr_cache[index_a] = value_a; 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric addr_t value_b = addr_cache[index_b]; 5860b57cec5SDimitry Andric if (value_b == LLDB_INVALID_ADDRESS) { 5870b57cec5SDimitry Andric value_b = symbols[index_b].GetAddressRef().GetFileAddress(); 5880b57cec5SDimitry Andric addr_cache[index_b] = value_b; 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric if (value_a == value_b) { 5920b57cec5SDimitry Andric // The if the values are equal, use the original symbol user ID 5930b57cec5SDimitry Andric lldb::user_id_t uid_a = symbols[index_a].GetID(); 5940b57cec5SDimitry Andric lldb::user_id_t uid_b = symbols[index_b].GetID(); 5950b57cec5SDimitry Andric if (uid_a < uid_b) 5960b57cec5SDimitry Andric return true; 5970b57cec5SDimitry Andric if (uid_a > uid_b) 5980b57cec5SDimitry Andric return false; 5990b57cec5SDimitry Andric return false; 6000b57cec5SDimitry Andric } else if (value_a < value_b) 6010b57cec5SDimitry Andric return true; 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric return false; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric }; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, 6090b57cec5SDimitry Andric bool remove_duplicates) const { 6100b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 611e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 6120b57cec5SDimitry Andric // No need to sort if we have zero or one items... 6130b57cec5SDimitry Andric if (indexes.size() <= 1) 6140b57cec5SDimitry Andric return; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // Sort the indexes in place using std::stable_sort. 6170b57cec5SDimitry Andric // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly 6180b57cec5SDimitry Andric // for performance, not correctness. The indexes vector tends to be "close" 6190b57cec5SDimitry Andric // to sorted, which the stable sort handles better. 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric SymbolIndexComparator comparator(m_symbols, addr_cache); 6240b57cec5SDimitry Andric std::stable_sort(indexes.begin(), indexes.end(), comparator); 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric // Remove any duplicates if requested 6270b57cec5SDimitry Andric if (remove_duplicates) { 6280b57cec5SDimitry Andric auto last = std::unique(indexes.begin(), indexes.end()); 6290b57cec5SDimitry Andric indexes.erase(last, indexes.end()); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 633*fe6060f1SDimitry Andric uint32_t Symtab::GetNameIndexes(ConstString symbol_name, 634*fe6060f1SDimitry Andric std::vector<uint32_t> &indexes) { 635*fe6060f1SDimitry Andric auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone); 636*fe6060f1SDimitry Andric const uint32_t count = name_to_index.GetValues(symbol_name, indexes); 637*fe6060f1SDimitry Andric if (count) 638*fe6060f1SDimitry Andric return count; 639*fe6060f1SDimitry Andric // Synthetic symbol names are not added to the name indexes, but they start 640*fe6060f1SDimitry Andric // with a prefix and end with a the symbol UserID. This allows users to find 641*fe6060f1SDimitry Andric // these symbols without having to add them to the name indexes. These 642*fe6060f1SDimitry Andric // queries will not happen very often since the names don't mean anything, so 643*fe6060f1SDimitry Andric // performance is not paramount in this case. 644*fe6060f1SDimitry Andric llvm::StringRef name = symbol_name.GetStringRef(); 645*fe6060f1SDimitry Andric // String the synthetic prefix if the name starts with it. 646*fe6060f1SDimitry Andric if (!name.consume_front(Symbol::GetSyntheticSymbolPrefix())) 647*fe6060f1SDimitry Andric return 0; // Not a synthetic symbol name 648*fe6060f1SDimitry Andric 649*fe6060f1SDimitry Andric // Extract the user ID from the symbol name 650*fe6060f1SDimitry Andric unsigned long long uid = 0; 651*fe6060f1SDimitry Andric if (getAsUnsignedInteger(name, /*Radix=*/10, uid)) 652*fe6060f1SDimitry Andric return 0; // Failed to extract the user ID as an integer 653*fe6060f1SDimitry Andric Symbol *symbol = FindSymbolByID(uid); 654*fe6060f1SDimitry Andric if (symbol == nullptr) 655*fe6060f1SDimitry Andric return 0; 656*fe6060f1SDimitry Andric const uint32_t symbol_idx = GetIndexForSymbol(symbol); 657*fe6060f1SDimitry Andric if (symbol_idx == UINT32_MAX) 658*fe6060f1SDimitry Andric return 0; 659*fe6060f1SDimitry Andric indexes.push_back(symbol_idx); 660*fe6060f1SDimitry Andric return 1; 661*fe6060f1SDimitry Andric } 662*fe6060f1SDimitry Andric 6630b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 6640b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6650b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6660b57cec5SDimitry Andric 667e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 6680b57cec5SDimitry Andric if (symbol_name) { 6690b57cec5SDimitry Andric if (!m_name_indexes_computed) 6700b57cec5SDimitry Andric InitNameIndexes(); 6710b57cec5SDimitry Andric 672*fe6060f1SDimitry Andric return GetNameIndexes(symbol_name, indexes); 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric return 0; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 6780b57cec5SDimitry Andric Debug symbol_debug_type, 6790b57cec5SDimitry Andric Visibility symbol_visibility, 6800b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6810b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6820b57cec5SDimitry Andric 683e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 6840b57cec5SDimitry Andric if (symbol_name) { 6850b57cec5SDimitry Andric const size_t old_size = indexes.size(); 6860b57cec5SDimitry Andric if (!m_name_indexes_computed) 6870b57cec5SDimitry Andric InitNameIndexes(); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric std::vector<uint32_t> all_name_indexes; 6900b57cec5SDimitry Andric const size_t name_match_count = 691*fe6060f1SDimitry Andric GetNameIndexes(symbol_name, all_name_indexes); 6920b57cec5SDimitry Andric for (size_t i = 0; i < name_match_count; ++i) { 6930b57cec5SDimitry Andric if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, 6940b57cec5SDimitry Andric symbol_visibility)) 6950b57cec5SDimitry Andric indexes.push_back(all_name_indexes[i]); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric return indexes.size() - old_size; 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric return 0; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric uint32_t 7030b57cec5SDimitry Andric Symtab::AppendSymbolIndexesWithNameAndType(ConstString symbol_name, 7040b57cec5SDimitry Andric SymbolType symbol_type, 7050b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 7060b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { 7090b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 7100b57cec5SDimitry Andric while (pos != indexes.end()) { 7110b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7120b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 7130b57cec5SDimitry Andric ++pos; 7140b57cec5SDimitry Andric else 7150b57cec5SDimitry Andric pos = indexes.erase(pos); 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric return indexes.size(); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 7220b57cec5SDimitry Andric ConstString symbol_name, SymbolType symbol_type, 7230b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 7240b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 7250b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, 7280b57cec5SDimitry Andric symbol_visibility, indexes) > 0) { 7290b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 7300b57cec5SDimitry Andric while (pos != indexes.end()) { 7310b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7320b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 7330b57cec5SDimitry Andric ++pos; 7340b57cec5SDimitry Andric else 7350b57cec5SDimitry Andric pos = indexes.erase(pos); 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric return indexes.size(); 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 7420b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 7430b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 7440b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 7470b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 7500b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7510b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 7520b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 7530b57cec5SDimitry Andric if (name) { 7540b57cec5SDimitry Andric if (regexp.Execute(name)) 7550b57cec5SDimitry Andric indexes.push_back(i); 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric return indexes.size() - prev_size; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 7630b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 7640b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 7650b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 7660b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 7690b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 7720b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7730b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 7740b57cec5SDimitry Andric if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 7750b57cec5SDimitry Andric continue; 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 7780b57cec5SDimitry Andric if (name) { 7790b57cec5SDimitry Andric if (regexp.Execute(name)) 7800b57cec5SDimitry Andric indexes.push_back(i); 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric return indexes.size() - prev_size; 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, 7880b57cec5SDimitry Andric Debug symbol_debug_type, 7890b57cec5SDimitry Andric Visibility symbol_visibility, 7900b57cec5SDimitry Andric uint32_t &start_idx) { 7910b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric const size_t count = m_symbols.size(); 7940b57cec5SDimitry Andric for (size_t idx = start_idx; idx < count; ++idx) { 7950b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7960b57cec5SDimitry Andric m_symbols[idx].GetType() == symbol_type) { 7970b57cec5SDimitry Andric if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { 7980b57cec5SDimitry Andric start_idx = idx; 7990b57cec5SDimitry Andric return &m_symbols[idx]; 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric return nullptr; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8069dba64beSDimitry Andric void 8070b57cec5SDimitry Andric Symtab::FindAllSymbolsWithNameAndType(ConstString name, 8080b57cec5SDimitry Andric SymbolType symbol_type, 8090b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 8100b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 8110b57cec5SDimitry Andric 812e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 8130b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 8140b57cec5SDimitry Andric // uniqued string NAME_STR below. 8150b57cec5SDimitry Andric if (!m_name_indexes_computed) 8160b57cec5SDimitry Andric InitNameIndexes(); 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric if (name) { 8190b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 8200b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 8210b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8259dba64beSDimitry Andric void Symtab::FindAllSymbolsWithNameAndType( 8260b57cec5SDimitry Andric ConstString name, SymbolType symbol_type, Debug symbol_debug_type, 8270b57cec5SDimitry Andric Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { 8280b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 8290b57cec5SDimitry Andric 830e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 8310b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 8320b57cec5SDimitry Andric // uniqued string NAME_STR below. 8330b57cec5SDimitry Andric if (!m_name_indexes_computed) 8340b57cec5SDimitry Andric InitNameIndexes(); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric if (name) { 8370b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 8380b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 8390b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 8400b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8449dba64beSDimitry Andric void Symtab::FindAllSymbolsMatchingRexExAndType( 8450b57cec5SDimitry Andric const RegularExpression ®ex, SymbolType symbol_type, 8460b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 8470b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 8480b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, 8510b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, 8550b57cec5SDimitry Andric SymbolType symbol_type, 8560b57cec5SDimitry Andric Debug symbol_debug_type, 8570b57cec5SDimitry Andric Visibility symbol_visibility) { 8580b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 859e8d8bef9SDimitry Andric LLDB_SCOPED_TIMER(); 8600b57cec5SDimitry Andric if (!m_name_indexes_computed) 8610b57cec5SDimitry Andric InitNameIndexes(); 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric if (name) { 8640b57cec5SDimitry Andric std::vector<uint32_t> matching_indexes; 8650b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 8660b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 8670b57cec5SDimitry Andric if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 8680b57cec5SDimitry Andric symbol_visibility, 8690b57cec5SDimitry Andric matching_indexes)) { 8700b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 8710b57cec5SDimitry Andric for (pos = matching_indexes.begin(); pos != end; ++pos) { 8720b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(*pos); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric if (symbol->Compare(name, symbol_type)) 8750b57cec5SDimitry Andric return symbol; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric return nullptr; 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric typedef struct { 8830b57cec5SDimitry Andric const Symtab *symtab; 8840b57cec5SDimitry Andric const addr_t file_addr; 8850b57cec5SDimitry Andric Symbol *match_symbol; 8860b57cec5SDimitry Andric const uint32_t *match_index_ptr; 8870b57cec5SDimitry Andric addr_t match_offset; 8880b57cec5SDimitry Andric } SymbolSearchInfo; 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric // Add all the section file start address & size to the RangeVector, recusively 8910b57cec5SDimitry Andric // adding any children sections. 8920b57cec5SDimitry Andric static void AddSectionsToRangeMap(SectionList *sectlist, 8930b57cec5SDimitry Andric RangeVector<addr_t, addr_t> §ion_ranges) { 8940b57cec5SDimitry Andric const int num_sections = sectlist->GetNumSections(0); 8950b57cec5SDimitry Andric for (int i = 0; i < num_sections; i++) { 8960b57cec5SDimitry Andric SectionSP sect_sp = sectlist->GetSectionAtIndex(i); 8970b57cec5SDimitry Andric if (sect_sp) { 8980b57cec5SDimitry Andric SectionList &child_sectlist = sect_sp->GetChildren(); 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric // If this section has children, add the children to the RangeVector. 9010b57cec5SDimitry Andric // Else add this section to the RangeVector. 9020b57cec5SDimitry Andric if (child_sectlist.GetNumSections(0) > 0) { 9030b57cec5SDimitry Andric AddSectionsToRangeMap(&child_sectlist, section_ranges); 9040b57cec5SDimitry Andric } else { 9050b57cec5SDimitry Andric size_t size = sect_sp->GetByteSize(); 9060b57cec5SDimitry Andric if (size > 0) { 9070b57cec5SDimitry Andric addr_t base_addr = sect_sp->GetFileAddress(); 9080b57cec5SDimitry Andric RangeVector<addr_t, addr_t>::Entry entry; 9090b57cec5SDimitry Andric entry.SetRangeBase(base_addr); 9100b57cec5SDimitry Andric entry.SetByteSize(size); 9110b57cec5SDimitry Andric section_ranges.Append(entry); 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric } 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric void Symtab::InitAddressIndexes() { 9190b57cec5SDimitry Andric // Protected function, no need to lock mutex... 9200b57cec5SDimitry Andric if (!m_file_addr_to_index_computed && !m_symbols.empty()) { 9210b57cec5SDimitry Andric m_file_addr_to_index_computed = true; 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric FileRangeToIndexMap::Entry entry; 9240b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 9250b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 9260b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 9270b57cec5SDimitry Andric if (pos->ValueIsAddress()) { 9280b57cec5SDimitry Andric entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); 9290b57cec5SDimitry Andric entry.SetByteSize(pos->GetByteSize()); 9300b57cec5SDimitry Andric entry.data = std::distance(begin, pos); 9310b57cec5SDimitry Andric m_file_addr_to_index.Append(entry); 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 9350b57cec5SDimitry Andric if (num_entries > 0) { 9360b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric // Create a RangeVector with the start & size of all the sections for 9390b57cec5SDimitry Andric // this objfile. We'll need to check this for any FileRangeToIndexMap 9400b57cec5SDimitry Andric // entries with an uninitialized size, which could potentially be a large 9410b57cec5SDimitry Andric // number so reconstituting the weak pointer is busywork when it is 9420b57cec5SDimitry Andric // invariant information. 9430b57cec5SDimitry Andric SectionList *sectlist = m_objfile->GetSectionList(); 9440b57cec5SDimitry Andric RangeVector<addr_t, addr_t> section_ranges; 9450b57cec5SDimitry Andric if (sectlist) { 9460b57cec5SDimitry Andric AddSectionsToRangeMap(sectlist, section_ranges); 9470b57cec5SDimitry Andric section_ranges.Sort(); 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric // Iterate through the FileRangeToIndexMap and fill in the size for any 9510b57cec5SDimitry Andric // entries that didn't already have a size from the Symbol (e.g. if we 9520b57cec5SDimitry Andric // have a plain linker symbol with an address only, instead of debug info 9530b57cec5SDimitry Andric // where we get an address and a size and a type, etc.) 9540b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; i++) { 9550b57cec5SDimitry Andric FileRangeToIndexMap::Entry *entry = 9560b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(i); 957c14a5a88SDimitry Andric if (entry->GetByteSize() == 0) { 9580b57cec5SDimitry Andric addr_t curr_base_addr = entry->GetRangeBase(); 9590b57cec5SDimitry Andric const RangeVector<addr_t, addr_t>::Entry *containing_section = 9600b57cec5SDimitry Andric section_ranges.FindEntryThatContains(curr_base_addr); 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric // Use the end of the section as the default max size of the symbol 9630b57cec5SDimitry Andric addr_t sym_size = 0; 9640b57cec5SDimitry Andric if (containing_section) { 9650b57cec5SDimitry Andric sym_size = 9660b57cec5SDimitry Andric containing_section->GetByteSize() - 9670b57cec5SDimitry Andric (entry->GetRangeBase() - containing_section->GetRangeBase()); 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric for (size_t j = i; j < num_entries; j++) { 9710b57cec5SDimitry Andric FileRangeToIndexMap::Entry *next_entry = 9720b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(j); 9730b57cec5SDimitry Andric addr_t next_base_addr = next_entry->GetRangeBase(); 9740b57cec5SDimitry Andric if (next_base_addr > curr_base_addr) { 9750b57cec5SDimitry Andric addr_t size_to_next_symbol = next_base_addr - curr_base_addr; 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric // Take the difference between this symbol and the next one as 9780b57cec5SDimitry Andric // its size, if it is less than the size of the section. 9790b57cec5SDimitry Andric if (sym_size == 0 || size_to_next_symbol < sym_size) { 9800b57cec5SDimitry Andric sym_size = size_to_next_symbol; 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric break; 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andric if (sym_size > 0) { 9870b57cec5SDimitry Andric entry->SetByteSize(sym_size); 9880b57cec5SDimitry Andric Symbol &symbol = m_symbols[entry->data]; 9890b57cec5SDimitry Andric symbol.SetByteSize(sym_size); 9900b57cec5SDimitry Andric symbol.SetSizeIsSynthesized(true); 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric // Sort again in case the range size changes the ordering 9960b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 9970b57cec5SDimitry Andric } 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric void Symtab::CalculateSymbolSizes() { 10020b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10030b57cec5SDimitry Andric // Size computation happens inside InitAddressIndexes. 10040b57cec5SDimitry Andric InitAddressIndexes(); 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { 10080b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10090b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 10100b57cec5SDimitry Andric InitAddressIndexes(); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 10130b57cec5SDimitry Andric m_file_addr_to_index.FindEntryStartsAt(file_addr); 10140b57cec5SDimitry Andric if (entry) { 10150b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 10160b57cec5SDimitry Andric if (symbol->GetFileAddress() == file_addr) 10170b57cec5SDimitry Andric return symbol; 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric return nullptr; 10200b57cec5SDimitry Andric } 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { 10230b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 10260b57cec5SDimitry Andric InitAddressIndexes(); 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 10290b57cec5SDimitry Andric m_file_addr_to_index.FindEntryThatContains(file_addr); 10300b57cec5SDimitry Andric if (entry) { 10310b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 10320b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) 10330b57cec5SDimitry Andric return symbol; 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric return nullptr; 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric void Symtab::ForEachSymbolContainingFileAddress( 10390b57cec5SDimitry Andric addr_t file_addr, std::function<bool(Symbol *)> const &callback) { 10400b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 10430b57cec5SDimitry Andric InitAddressIndexes(); 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric std::vector<uint32_t> all_addr_indexes; 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric // Get all symbols with file_addr 10480b57cec5SDimitry Andric const size_t addr_match_count = 10490b57cec5SDimitry Andric m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, 10500b57cec5SDimitry Andric all_addr_indexes); 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric for (size_t i = 0; i < addr_match_count; ++i) { 10530b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); 10540b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) { 10550b57cec5SDimitry Andric if (!callback(symbol)) 10560b57cec5SDimitry Andric break; 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric } 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric void Symtab::SymbolIndicesToSymbolContextList( 10620b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { 10630b57cec5SDimitry Andric // No need to protect this call using m_mutex all other method calls are 10640b57cec5SDimitry Andric // already thread safe. 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric const bool merge_symbol_into_function = true; 10670b57cec5SDimitry Andric size_t num_indices = symbol_indexes.size(); 10680b57cec5SDimitry Andric if (num_indices > 0) { 10690b57cec5SDimitry Andric SymbolContext sc; 10700b57cec5SDimitry Andric sc.module_sp = m_objfile->GetModule(); 10710b57cec5SDimitry Andric for (size_t i = 0; i < num_indices; i++) { 10720b57cec5SDimitry Andric sc.symbol = SymbolAtIndex(symbol_indexes[i]); 10730b57cec5SDimitry Andric if (sc.symbol) 10740b57cec5SDimitry Andric sc_list.AppendIfUnique(sc, merge_symbol_into_function); 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric 10799dba64beSDimitry Andric void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, 10800b57cec5SDimitry Andric SymbolContextList &sc_list) { 10810b57cec5SDimitry Andric std::vector<uint32_t> symbol_indexes; 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric // eFunctionNameTypeAuto should be pre-resolved by a call to 10840b57cec5SDimitry Andric // Module::LookupInfo::LookupInfo() 10850b57cec5SDimitry Andric assert((name_type_mask & eFunctionNameTypeAuto) == 0); 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { 10880b57cec5SDimitry Andric std::vector<uint32_t> temp_symbol_indexes; 10890b57cec5SDimitry Andric FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 10920b57cec5SDimitry Andric if (temp_symbol_indexes_size > 0) { 10930b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10940b57cec5SDimitry Andric for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { 10950b57cec5SDimitry Andric SymbolContext sym_ctx; 10960b57cec5SDimitry Andric sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); 10970b57cec5SDimitry Andric if (sym_ctx.symbol) { 10980b57cec5SDimitry Andric switch (sym_ctx.symbol->GetType()) { 10990b57cec5SDimitry Andric case eSymbolTypeCode: 11000b57cec5SDimitry Andric case eSymbolTypeResolver: 11010b57cec5SDimitry Andric case eSymbolTypeReExported: 11020b57cec5SDimitry Andric symbol_indexes.push_back(temp_symbol_indexes[i]); 11030b57cec5SDimitry Andric break; 11040b57cec5SDimitry Andric default: 11050b57cec5SDimitry Andric break; 11060b57cec5SDimitry Andric } 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric if (!m_name_indexes_computed) 11130b57cec5SDimitry Andric InitNameIndexes(); 11140b57cec5SDimitry Andric 1115*fe6060f1SDimitry Andric for (lldb::FunctionNameType type : 1116*fe6060f1SDimitry Andric {lldb::eFunctionNameTypeBase, lldb::eFunctionNameTypeMethod, 1117*fe6060f1SDimitry Andric lldb::eFunctionNameTypeSelector}) { 1118*fe6060f1SDimitry Andric if (name_type_mask & type) { 1119*fe6060f1SDimitry Andric auto map = GetNameToSymbolIndexMap(type); 1120*fe6060f1SDimitry Andric 11210b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 1122*fe6060f1SDimitry Andric for (match = map.FindFirstValueForName(name); match != nullptr; 1123*fe6060f1SDimitry Andric match = map.FindNextValueForName(match)) { 11240b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric if (!symbol_indexes.empty()) { 11300b57cec5SDimitry Andric llvm::sort(symbol_indexes.begin(), symbol_indexes.end()); 11310b57cec5SDimitry Andric symbol_indexes.erase( 11320b57cec5SDimitry Andric std::unique(symbol_indexes.begin(), symbol_indexes.end()), 11330b57cec5SDimitry Andric symbol_indexes.end()); 11340b57cec5SDimitry Andric SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric const Symbol *Symtab::GetParent(Symbol *child_symbol) const { 11390b57cec5SDimitry Andric uint32_t child_idx = GetIndexForSymbol(child_symbol); 11400b57cec5SDimitry Andric if (child_idx != UINT32_MAX && child_idx > 0) { 11410b57cec5SDimitry Andric for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { 11420b57cec5SDimitry Andric const Symbol *symbol = SymbolAtIndex(idx); 11430b57cec5SDimitry Andric const uint32_t sibling_idx = symbol->GetSiblingIndex(); 11440b57cec5SDimitry Andric if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) 11450b57cec5SDimitry Andric return symbol; 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric } 11480b57cec5SDimitry Andric return nullptr; 11490b57cec5SDimitry Andric } 1150