10b57cec5SDimitry Andric //===-- Symtab.cpp ----------------------------------------------*- C++ -*-===// 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 "Plugins/Language/ObjC/ObjCLanguage.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Core/RichManglingContext.h" 160b57cec5SDimitry Andric #include "lldb/Core/Section.h" 170b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/Symtab.h" 210b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 230b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace lldb; 280b57cec5SDimitry Andric using namespace lldb_private; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric Symtab::Symtab(ObjectFile *objfile) 31480093f4SDimitry Andric : m_objfile(objfile), m_symbols(), m_file_addr_to_index(*this), 320b57cec5SDimitry Andric m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false), 330b57cec5SDimitry Andric m_name_indexes_computed(false) {} 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric Symtab::~Symtab() {} 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric void Symtab::Reserve(size_t count) { 380b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 390b57cec5SDimitry Andric // when calling this function to avoid performance issues. 400b57cec5SDimitry Andric m_symbols.reserve(count); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric Symbol *Symtab::Resize(size_t count) { 440b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 450b57cec5SDimitry Andric // when calling this function to avoid performance issues. 460b57cec5SDimitry Andric m_symbols.resize(count); 470b57cec5SDimitry Andric return m_symbols.empty() ? nullptr : &m_symbols[0]; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric uint32_t Symtab::AddSymbol(const Symbol &symbol) { 510b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 520b57cec5SDimitry Andric // when calling this function to avoid performance issues. 530b57cec5SDimitry Andric uint32_t symbol_idx = m_symbols.size(); 540b57cec5SDimitry Andric m_name_to_index.Clear(); 550b57cec5SDimitry Andric m_file_addr_to_index.Clear(); 560b57cec5SDimitry Andric m_symbols.push_back(symbol); 570b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 580b57cec5SDimitry Andric m_name_indexes_computed = false; 590b57cec5SDimitry Andric return symbol_idx; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric size_t Symtab::GetNumSymbols() const { 630b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 640b57cec5SDimitry Andric return m_symbols.size(); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric void Symtab::SectionFileAddressesChanged() { 680b57cec5SDimitry Andric m_name_to_index.Clear(); 690b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 72480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order, 73480093f4SDimitry Andric Mangled::NamePreference name_preference) { 740b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 770b57cec5SDimitry Andric s->Indent(); 780b57cec5SDimitry Andric const FileSpec &file_spec = m_objfile->GetFileSpec(); 790b57cec5SDimitry Andric const char *object_name = nullptr; 800b57cec5SDimitry Andric if (m_objfile->GetModule()) 810b57cec5SDimitry Andric object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric if (file_spec) 840b57cec5SDimitry Andric s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, 850b57cec5SDimitry Andric file_spec.GetPath().c_str(), object_name ? "(" : "", 860b57cec5SDimitry Andric object_name ? object_name : "", object_name ? ")" : "", 870b57cec5SDimitry Andric (uint64_t)m_symbols.size()); 880b57cec5SDimitry Andric else 890b57cec5SDimitry Andric s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric if (!m_symbols.empty()) { 920b57cec5SDimitry Andric switch (sort_order) { 930b57cec5SDimitry Andric case eSortOrderNone: { 940b57cec5SDimitry Andric s->PutCString(":\n"); 950b57cec5SDimitry Andric DumpSymbolHeader(s); 960b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 970b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 980b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 990b57cec5SDimitry Andric s->Indent(); 100480093f4SDimitry Andric pos->Dump(s, target, std::distance(begin, pos), name_preference); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } break; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric case eSortOrderByName: { 1050b57cec5SDimitry Andric // Although we maintain a lookup by exact name map, the table isn't 1060b57cec5SDimitry Andric // sorted by name. So we must make the ordered symbol list up ourselves. 1070b57cec5SDimitry Andric s->PutCString(" (sorted by name):\n"); 1080b57cec5SDimitry Andric DumpSymbolHeader(s); 109480093f4SDimitry Andric 110480093f4SDimitry Andric std::multimap<llvm::StringRef, const Symbol *> name_map; 1110b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 1120b57cec5SDimitry Andric pos != end; ++pos) { 1130b57cec5SDimitry Andric const char *name = pos->GetName().AsCString(); 1140b57cec5SDimitry Andric if (name && name[0]) 1150b57cec5SDimitry Andric name_map.insert(std::make_pair(name, &(*pos))); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 118480093f4SDimitry Andric for (const auto &name_to_symbol : name_map) { 119480093f4SDimitry Andric const Symbol *symbol = name_to_symbol.second; 1200b57cec5SDimitry Andric s->Indent(); 121480093f4SDimitry Andric symbol->Dump(s, target, symbol - &m_symbols[0], name_preference); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } break; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric case eSortOrderByAddress: 1260b57cec5SDimitry Andric s->PutCString(" (sorted by address):\n"); 1270b57cec5SDimitry Andric DumpSymbolHeader(s); 1280b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 1290b57cec5SDimitry Andric InitAddressIndexes(); 1300b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 1310b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; ++i) { 1320b57cec5SDimitry Andric s->Indent(); 1330b57cec5SDimitry Andric const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; 134480093f4SDimitry Andric m_symbols[symbol_idx].Dump(s, target, symbol_idx, name_preference); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric break; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric } else { 1390b57cec5SDimitry Andric s->PutCString("\n"); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 143480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes, 144480093f4SDimitry Andric Mangled::NamePreference name_preference) const { 1450b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric const size_t num_symbols = GetNumSymbols(); 1480b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 1490b57cec5SDimitry Andric s->Indent(); 1500b57cec5SDimitry Andric s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", 1510b57cec5SDimitry Andric (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); 1520b57cec5SDimitry Andric s->IndentMore(); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric if (!indexes.empty()) { 1550b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos; 1560b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator end = indexes.end(); 1570b57cec5SDimitry Andric DumpSymbolHeader(s); 1580b57cec5SDimitry Andric for (pos = indexes.begin(); pos != end; ++pos) { 1590b57cec5SDimitry Andric size_t idx = *pos; 1600b57cec5SDimitry Andric if (idx < num_symbols) { 1610b57cec5SDimitry Andric s->Indent(); 162480093f4SDimitry Andric m_symbols[idx].Dump(s, target, idx, name_preference); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric s->IndentLess(); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void Symtab::DumpSymbolHeader(Stream *s) { 1700b57cec5SDimitry Andric s->Indent(" Debug symbol\n"); 1710b57cec5SDimitry Andric s->Indent(" |Synthetic symbol\n"); 1720b57cec5SDimitry Andric s->Indent(" ||Externally Visible\n"); 1730b57cec5SDimitry Andric s->Indent(" |||\n"); 1740b57cec5SDimitry Andric s->Indent("Index UserID DSX Type File Address/Value Load " 1750b57cec5SDimitry Andric "Address Size Flags Name\n"); 1760b57cec5SDimitry Andric s->Indent("------- ------ --- --------------- ------------------ " 1770b57cec5SDimitry Andric "------------------ ------------------ ---------- " 1780b57cec5SDimitry Andric "----------------------------------\n"); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric static int CompareSymbolID(const void *key, const void *p) { 1820b57cec5SDimitry Andric const user_id_t match_uid = *(const user_id_t *)key; 1830b57cec5SDimitry Andric const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); 1840b57cec5SDimitry Andric if (match_uid < symbol_uid) 1850b57cec5SDimitry Andric return -1; 1860b57cec5SDimitry Andric if (match_uid > symbol_uid) 1870b57cec5SDimitry Andric return 1; 1880b57cec5SDimitry Andric return 0; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const { 1920b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric Symbol *symbol = 1950b57cec5SDimitry Andric (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(), 1960b57cec5SDimitry Andric sizeof(m_symbols[0]), CompareSymbolID); 1970b57cec5SDimitry Andric return symbol; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric Symbol *Symtab::SymbolAtIndex(size_t idx) { 2010b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 2020b57cec5SDimitry Andric // when calling this function to avoid performance issues. 2030b57cec5SDimitry Andric if (idx < m_symbols.size()) 2040b57cec5SDimitry Andric return &m_symbols[idx]; 2050b57cec5SDimitry Andric return nullptr; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric const Symbol *Symtab::SymbolAtIndex(size_t idx) const { 2090b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 2100b57cec5SDimitry Andric // when calling this function to avoid performance issues. 2110b57cec5SDimitry Andric if (idx < m_symbols.size()) 2120b57cec5SDimitry Andric return &m_symbols[idx]; 2130b57cec5SDimitry Andric return nullptr; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric static bool lldb_skip_name(llvm::StringRef mangled, 2170b57cec5SDimitry Andric Mangled::ManglingScheme scheme) { 2180b57cec5SDimitry Andric switch (scheme) { 2190b57cec5SDimitry Andric case Mangled::eManglingSchemeItanium: { 2200b57cec5SDimitry Andric if (mangled.size() < 3 || !mangled.startswith("_Z")) 2210b57cec5SDimitry Andric return true; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric // Avoid the following types of symbols in the index. 2240b57cec5SDimitry Andric switch (mangled[2]) { 2250b57cec5SDimitry Andric case 'G': // guard variables 2260b57cec5SDimitry Andric case 'T': // virtual tables, VTT structures, typeinfo structures + names 2270b57cec5SDimitry Andric case 'Z': // named local entities (if we eventually handle 2280b57cec5SDimitry Andric // eSymbolTypeData, we will want this back) 2290b57cec5SDimitry Andric return true; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric default: 2320b57cec5SDimitry Andric break; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric // Include this name in the index. 2360b57cec5SDimitry Andric return false; 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric // No filters for this scheme yet. Include all names in indexing. 2400b57cec5SDimitry Andric case Mangled::eManglingSchemeMSVC: 2410b57cec5SDimitry Andric return false; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Don't try and demangle things we can't categorize. 2440b57cec5SDimitry Andric case Mangled::eManglingSchemeNone: 2450b57cec5SDimitry Andric return true; 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric llvm_unreachable("unknown scheme!"); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric void Symtab::InitNameIndexes() { 2510b57cec5SDimitry Andric // Protected function, no need to lock mutex... 2520b57cec5SDimitry Andric if (!m_name_indexes_computed) { 2530b57cec5SDimitry Andric m_name_indexes_computed = true; 2540b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 2550b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 2560b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 2570b57cec5SDimitry Andric const size_t num_symbols = m_symbols.size(); 2580b57cec5SDimitry Andric m_name_to_index.Reserve(num_symbols); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // The "const char *" in "class_contexts" and backlog::value_type::second 2610b57cec5SDimitry Andric // must come from a ConstString::GetCString() 2620b57cec5SDimitry Andric std::set<const char *> class_contexts; 2630b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog; 2640b57cec5SDimitry Andric backlog.reserve(num_symbols / 2); 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric // Instantiation of the demangler is expensive, so better use a single one 2670b57cec5SDimitry Andric // for all entries during batch processing. 2680b57cec5SDimitry Andric RichManglingContext rmc; 2690b57cec5SDimitry Andric for (uint32_t value = 0; value < num_symbols; ++value) { 2700b57cec5SDimitry Andric Symbol *symbol = &m_symbols[value]; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric // Don't let trampolines get into the lookup by name map If we ever need 2730b57cec5SDimitry Andric // the trampoline symbols to be searchable by name we can remove this and 2740b57cec5SDimitry Andric // then possibly add a new bool to any of the Symtab functions that 2750b57cec5SDimitry Andric // lookup symbols by name to indicate if they want trampolines. 2760b57cec5SDimitry Andric if (symbol->IsTrampoline()) 2770b57cec5SDimitry Andric continue; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // If the symbol's name string matched a Mangled::ManglingScheme, it is 2800b57cec5SDimitry Andric // stored in the mangled field. 2810b57cec5SDimitry Andric Mangled &mangled = symbol->GetMangled(); 2820b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) { 2830b57cec5SDimitry Andric m_name_to_index.Append(name, value); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 2860b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 2870b57cec5SDimitry Andric // the annotations. 2880b57cec5SDimitry Andric ConstString stripped = ConstString( 2890b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 2900b57cec5SDimitry Andric m_name_to_index.Append(stripped, value); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric const SymbolType type = symbol->GetType(); 2940b57cec5SDimitry Andric if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { 2950b57cec5SDimitry Andric if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name)) 2960b57cec5SDimitry Andric RegisterMangledNameEntry(value, class_contexts, backlog, rmc); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Symbol name strings that didn't match a Mangled::ManglingScheme, are 3010b57cec5SDimitry Andric // stored in the demangled field. 3020b57cec5SDimitry Andric if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) { 3030b57cec5SDimitry Andric m_name_to_index.Append(name, value); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 3060b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 3070b57cec5SDimitry Andric // the annotations. 3080b57cec5SDimitry Andric name = ConstString( 3090b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 3100b57cec5SDimitry Andric m_name_to_index.Append(name, value); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // If the demangled name turns out to be an ObjC name, and is a category 3140b57cec5SDimitry Andric // name, add the version without categories to the index too. 3150b57cec5SDimitry Andric ObjCLanguage::MethodName objc_method(name.GetStringRef(), true); 3160b57cec5SDimitry Andric if (objc_method.IsValid(true)) { 3170b57cec5SDimitry Andric m_selector_to_index.Append(objc_method.GetSelector(), value); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric if (ConstString objc_method_no_category = 3200b57cec5SDimitry Andric objc_method.GetFullNameWithoutCategory(true)) 3210b57cec5SDimitry Andric m_name_to_index.Append(objc_method_no_category, value); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric for (const auto &record : backlog) { 3270b57cec5SDimitry Andric RegisterBacklogEntry(record.first, record.second, class_contexts); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric m_name_to_index.Sort(); 3310b57cec5SDimitry Andric m_name_to_index.SizeToFit(); 3320b57cec5SDimitry Andric m_selector_to_index.Sort(); 3330b57cec5SDimitry Andric m_selector_to_index.SizeToFit(); 3340b57cec5SDimitry Andric m_basename_to_index.Sort(); 3350b57cec5SDimitry Andric m_basename_to_index.SizeToFit(); 3360b57cec5SDimitry Andric m_method_to_index.Sort(); 3370b57cec5SDimitry Andric m_method_to_index.SizeToFit(); 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric void Symtab::RegisterMangledNameEntry( 3420b57cec5SDimitry Andric uint32_t value, std::set<const char *> &class_contexts, 3430b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, 3440b57cec5SDimitry Andric RichManglingContext &rmc) { 3450b57cec5SDimitry Andric // Only register functions that have a base name. 3460b57cec5SDimitry Andric rmc.ParseFunctionBaseName(); 3470b57cec5SDimitry Andric llvm::StringRef base_name = rmc.GetBufferRef(); 3480b57cec5SDimitry Andric if (base_name.empty()) 3490b57cec5SDimitry Andric return; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric // The base name will be our entry's name. 3520b57cec5SDimitry Andric NameToIndexMap::Entry entry(ConstString(base_name), value); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric rmc.ParseFunctionDeclContextName(); 3550b57cec5SDimitry Andric llvm::StringRef decl_context = rmc.GetBufferRef(); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric // Register functions with no context. 3580b57cec5SDimitry Andric if (decl_context.empty()) { 3590b57cec5SDimitry Andric // This has to be a basename 3600b57cec5SDimitry Andric m_basename_to_index.Append(entry); 3610b57cec5SDimitry Andric // If there is no context (no namespaces or class scopes that come before 3620b57cec5SDimitry Andric // the function name) then this also could be a fullname. 3630b57cec5SDimitry Andric m_name_to_index.Append(entry); 3640b57cec5SDimitry Andric return; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric // Make sure we have a pool-string pointer and see if we already know the 3680b57cec5SDimitry Andric // context name. 3690b57cec5SDimitry Andric const char *decl_context_ccstr = ConstString(decl_context).GetCString(); 3700b57cec5SDimitry Andric auto it = class_contexts.find(decl_context_ccstr); 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // Register constructors and destructors. They are methods and create 3730b57cec5SDimitry Andric // declaration contexts. 3740b57cec5SDimitry Andric if (rmc.IsCtorOrDtor()) { 3750b57cec5SDimitry Andric m_method_to_index.Append(entry); 3760b57cec5SDimitry Andric if (it == class_contexts.end()) 3770b57cec5SDimitry Andric class_contexts.insert(it, decl_context_ccstr); 3780b57cec5SDimitry Andric return; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // Register regular methods with a known declaration context. 3820b57cec5SDimitry Andric if (it != class_contexts.end()) { 3830b57cec5SDimitry Andric m_method_to_index.Append(entry); 3840b57cec5SDimitry Andric return; 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // Regular methods in unknown declaration contexts are put to the backlog. We 3880b57cec5SDimitry Andric // will revisit them once we processed all remaining symbols. 3890b57cec5SDimitry Andric backlog.push_back(std::make_pair(entry, decl_context_ccstr)); 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric void Symtab::RegisterBacklogEntry( 3930b57cec5SDimitry Andric const NameToIndexMap::Entry &entry, const char *decl_context, 3940b57cec5SDimitry Andric const std::set<const char *> &class_contexts) { 3950b57cec5SDimitry Andric auto it = class_contexts.find(decl_context); 3960b57cec5SDimitry Andric if (it != class_contexts.end()) { 3970b57cec5SDimitry Andric m_method_to_index.Append(entry); 3980b57cec5SDimitry Andric } else { 3990b57cec5SDimitry Andric // If we got here, we have something that had a context (was inside 4000b57cec5SDimitry Andric // a namespace or class) yet we don't know the entry 4010b57cec5SDimitry Andric m_method_to_index.Append(entry); 4020b57cec5SDimitry Andric m_basename_to_index.Append(entry); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric void Symtab::PreloadSymbols() { 4070b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4080b57cec5SDimitry Andric InitNameIndexes(); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, 4120b57cec5SDimitry Andric bool add_demangled, bool add_mangled, 4130b57cec5SDimitry Andric NameToIndexMap &name_to_index_map) const { 4140b57cec5SDimitry Andric if (add_demangled || add_mangled) { 4150b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 4160b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 4170b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 4200b57cec5SDimitry Andric const size_t num_indexes = indexes.size(); 4210b57cec5SDimitry Andric for (size_t i = 0; i < num_indexes; ++i) { 4220b57cec5SDimitry Andric uint32_t value = indexes[i]; 4230b57cec5SDimitry Andric assert(i < m_symbols.size()); 4240b57cec5SDimitry Andric const Symbol *symbol = &m_symbols[value]; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric const Mangled &mangled = symbol->GetMangled(); 4270b57cec5SDimitry Andric if (add_demangled) { 4280b57cec5SDimitry Andric if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) 4290b57cec5SDimitry Andric name_to_index_map.Append(name, value); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric if (add_mangled) { 4330b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) 4340b57cec5SDimitry Andric name_to_index_map.Append(name, value); 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 4410b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 4420b57cec5SDimitry Andric uint32_t start_idx, 4430b57cec5SDimitry Andric uint32_t end_index) const { 4440b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 4510b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 4520b57cec5SDimitry Andric indexes.push_back(i); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric return indexes.size() - prev_size; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue( 4590b57cec5SDimitry Andric SymbolType symbol_type, uint32_t flags_value, 4600b57cec5SDimitry Andric std::vector<uint32_t> &indexes, uint32_t start_idx, 4610b57cec5SDimitry Andric uint32_t end_index) const { 4620b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 4690b57cec5SDimitry Andric if ((symbol_type == eSymbolTypeAny || 4700b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) && 4710b57cec5SDimitry Andric m_symbols[i].GetFlags() == flags_value) 4720b57cec5SDimitry Andric indexes.push_back(i); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric return indexes.size() - prev_size; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 4790b57cec5SDimitry Andric Debug symbol_debug_type, 4800b57cec5SDimitry Andric Visibility symbol_visibility, 4810b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 4820b57cec5SDimitry Andric uint32_t start_idx, 4830b57cec5SDimitry Andric uint32_t end_index) const { 4840b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 4910b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 4920b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 4930b57cec5SDimitry Andric if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 4940b57cec5SDimitry Andric indexes.push_back(i); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric return indexes.size() - prev_size; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const { 5020b57cec5SDimitry Andric if (!m_symbols.empty()) { 5030b57cec5SDimitry Andric const Symbol *first_symbol = &m_symbols[0]; 5040b57cec5SDimitry Andric if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 5050b57cec5SDimitry Andric return symbol - first_symbol; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric return UINT32_MAX; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric struct SymbolSortInfo { 5110b57cec5SDimitry Andric const bool sort_by_load_addr; 5120b57cec5SDimitry Andric const Symbol *symbols; 5130b57cec5SDimitry Andric }; 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric namespace { 5160b57cec5SDimitry Andric struct SymbolIndexComparator { 5170b57cec5SDimitry Andric const std::vector<Symbol> &symbols; 5180b57cec5SDimitry Andric std::vector<lldb::addr_t> &addr_cache; 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric // Getting from the symbol to the Address to the File Address involves some 5210b57cec5SDimitry Andric // work. Since there are potentially many symbols here, and we're using this 5220b57cec5SDimitry Andric // for sorting so we're going to be computing the address many times, cache 5230b57cec5SDimitry Andric // that in addr_cache. The array passed in has to be the same size as the 5240b57cec5SDimitry Andric // symbols array passed into the member variable symbols, and should be 5250b57cec5SDimitry Andric // initialized with LLDB_INVALID_ADDRESS. 5260b57cec5SDimitry Andric // NOTE: You have to make addr_cache externally and pass it in because 5270b57cec5SDimitry Andric // std::stable_sort 5280b57cec5SDimitry Andric // makes copies of the comparator it is initially passed in, and you end up 5290b57cec5SDimitry Andric // spending huge amounts of time copying this array... 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric SymbolIndexComparator(const std::vector<Symbol> &s, 5320b57cec5SDimitry Andric std::vector<lldb::addr_t> &a) 5330b57cec5SDimitry Andric : symbols(s), addr_cache(a) { 5340b57cec5SDimitry Andric assert(symbols.size() == addr_cache.size()); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric bool operator()(uint32_t index_a, uint32_t index_b) { 5370b57cec5SDimitry Andric addr_t value_a = addr_cache[index_a]; 5380b57cec5SDimitry Andric if (value_a == LLDB_INVALID_ADDRESS) { 5390b57cec5SDimitry Andric value_a = symbols[index_a].GetAddressRef().GetFileAddress(); 5400b57cec5SDimitry Andric addr_cache[index_a] = value_a; 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric addr_t value_b = addr_cache[index_b]; 5440b57cec5SDimitry Andric if (value_b == LLDB_INVALID_ADDRESS) { 5450b57cec5SDimitry Andric value_b = symbols[index_b].GetAddressRef().GetFileAddress(); 5460b57cec5SDimitry Andric addr_cache[index_b] = value_b; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric if (value_a == value_b) { 5500b57cec5SDimitry Andric // The if the values are equal, use the original symbol user ID 5510b57cec5SDimitry Andric lldb::user_id_t uid_a = symbols[index_a].GetID(); 5520b57cec5SDimitry Andric lldb::user_id_t uid_b = symbols[index_b].GetID(); 5530b57cec5SDimitry Andric if (uid_a < uid_b) 5540b57cec5SDimitry Andric return true; 5550b57cec5SDimitry Andric if (uid_a > uid_b) 5560b57cec5SDimitry Andric return false; 5570b57cec5SDimitry Andric return false; 5580b57cec5SDimitry Andric } else if (value_a < value_b) 5590b57cec5SDimitry Andric return true; 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric return false; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric }; 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, 5670b57cec5SDimitry Andric bool remove_duplicates) const { 5680b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 5710b57cec5SDimitry Andric Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 5720b57cec5SDimitry Andric // No need to sort if we have zero or one items... 5730b57cec5SDimitry Andric if (indexes.size() <= 1) 5740b57cec5SDimitry Andric return; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Sort the indexes in place using std::stable_sort. 5770b57cec5SDimitry Andric // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly 5780b57cec5SDimitry Andric // for performance, not correctness. The indexes vector tends to be "close" 5790b57cec5SDimitry Andric // to sorted, which the stable sort handles better. 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric SymbolIndexComparator comparator(m_symbols, addr_cache); 5840b57cec5SDimitry Andric std::stable_sort(indexes.begin(), indexes.end(), comparator); 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric // Remove any duplicates if requested 5870b57cec5SDimitry Andric if (remove_duplicates) { 5880b57cec5SDimitry Andric auto last = std::unique(indexes.begin(), indexes.end()); 5890b57cec5SDimitry Andric indexes.erase(last, indexes.end()); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 5940b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 5950b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 5980b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 5990b57cec5SDimitry Andric if (symbol_name) { 6000b57cec5SDimitry Andric if (!m_name_indexes_computed) 6010b57cec5SDimitry Andric InitNameIndexes(); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric return m_name_to_index.GetValues(symbol_name, indexes); 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric return 0; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 6090b57cec5SDimitry Andric Debug symbol_debug_type, 6100b57cec5SDimitry Andric Visibility symbol_visibility, 6110b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6120b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 6150b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 6160b57cec5SDimitry Andric if (symbol_name) { 6170b57cec5SDimitry Andric const size_t old_size = indexes.size(); 6180b57cec5SDimitry Andric if (!m_name_indexes_computed) 6190b57cec5SDimitry Andric InitNameIndexes(); 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric std::vector<uint32_t> all_name_indexes; 6220b57cec5SDimitry Andric const size_t name_match_count = 6230b57cec5SDimitry Andric m_name_to_index.GetValues(symbol_name, all_name_indexes); 6240b57cec5SDimitry Andric for (size_t i = 0; i < name_match_count; ++i) { 6250b57cec5SDimitry Andric if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, 6260b57cec5SDimitry Andric symbol_visibility)) 6270b57cec5SDimitry Andric indexes.push_back(all_name_indexes[i]); 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric return indexes.size() - old_size; 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric return 0; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric uint32_t 6350b57cec5SDimitry Andric Symtab::AppendSymbolIndexesWithNameAndType(ConstString symbol_name, 6360b57cec5SDimitry Andric SymbolType symbol_type, 6370b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6380b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { 6410b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 6420b57cec5SDimitry Andric while (pos != indexes.end()) { 6430b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 6440b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 6450b57cec5SDimitry Andric ++pos; 6460b57cec5SDimitry Andric else 6470b57cec5SDimitry Andric pos = indexes.erase(pos); 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric return indexes.size(); 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 6540b57cec5SDimitry Andric ConstString symbol_name, SymbolType symbol_type, 6550b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 6560b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6570b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, 6600b57cec5SDimitry Andric symbol_visibility, indexes) > 0) { 6610b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 6620b57cec5SDimitry Andric while (pos != indexes.end()) { 6630b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 6640b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 6650b57cec5SDimitry Andric ++pos; 6660b57cec5SDimitry Andric else 6670b57cec5SDimitry Andric pos = indexes.erase(pos); 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric return indexes.size(); 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 6740b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 6750b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6760b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 6790b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 6820b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 6830b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 6840b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 6850b57cec5SDimitry Andric if (name) { 6860b57cec5SDimitry Andric if (regexp.Execute(name)) 6870b57cec5SDimitry Andric indexes.push_back(i); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric return indexes.size() - prev_size; 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 6950b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 6960b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 6970b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 6980b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 7010b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 7040b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7050b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 7060b57cec5SDimitry Andric if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 7070b57cec5SDimitry Andric continue; 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 7100b57cec5SDimitry Andric if (name) { 7110b57cec5SDimitry Andric if (regexp.Execute(name)) 7120b57cec5SDimitry Andric indexes.push_back(i); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric return indexes.size() - prev_size; 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, 7200b57cec5SDimitry Andric Debug symbol_debug_type, 7210b57cec5SDimitry Andric Visibility symbol_visibility, 7220b57cec5SDimitry Andric uint32_t &start_idx) { 7230b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric const size_t count = m_symbols.size(); 7260b57cec5SDimitry Andric for (size_t idx = start_idx; idx < count; ++idx) { 7270b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 7280b57cec5SDimitry Andric m_symbols[idx].GetType() == symbol_type) { 7290b57cec5SDimitry Andric if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { 7300b57cec5SDimitry Andric start_idx = idx; 7310b57cec5SDimitry Andric return &m_symbols[idx]; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric return nullptr; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7389dba64beSDimitry Andric void 7390b57cec5SDimitry Andric Symtab::FindAllSymbolsWithNameAndType(ConstString name, 7400b57cec5SDimitry Andric SymbolType symbol_type, 7410b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 7420b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 7450b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 7460b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 7470b57cec5SDimitry Andric // uniqued string NAME_STR below. 7480b57cec5SDimitry Andric if (!m_name_indexes_computed) 7490b57cec5SDimitry Andric InitNameIndexes(); 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric if (name) { 7520b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 7530b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 7540b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7589dba64beSDimitry Andric void Symtab::FindAllSymbolsWithNameAndType( 7590b57cec5SDimitry Andric ConstString name, SymbolType symbol_type, Debug symbol_debug_type, 7600b57cec5SDimitry Andric Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { 7610b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 7640b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 7650b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 7660b57cec5SDimitry Andric // uniqued string NAME_STR below. 7670b57cec5SDimitry Andric if (!m_name_indexes_computed) 7680b57cec5SDimitry Andric InitNameIndexes(); 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric if (name) { 7710b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 7720b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 7730b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 7740b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7789dba64beSDimitry Andric void Symtab::FindAllSymbolsMatchingRexExAndType( 7790b57cec5SDimitry Andric const RegularExpression ®ex, SymbolType symbol_type, 7800b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 7810b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 7820b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, 7850b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, 7890b57cec5SDimitry Andric SymbolType symbol_type, 7900b57cec5SDimitry Andric Debug symbol_debug_type, 7910b57cec5SDimitry Andric Visibility symbol_visibility) { 7920b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 7950b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 7960b57cec5SDimitry Andric if (!m_name_indexes_computed) 7970b57cec5SDimitry Andric InitNameIndexes(); 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric if (name) { 8000b57cec5SDimitry Andric std::vector<uint32_t> matching_indexes; 8010b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 8020b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 8030b57cec5SDimitry Andric if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 8040b57cec5SDimitry Andric symbol_visibility, 8050b57cec5SDimitry Andric matching_indexes)) { 8060b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 8070b57cec5SDimitry Andric for (pos = matching_indexes.begin(); pos != end; ++pos) { 8080b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(*pos); 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric if (symbol->Compare(name, symbol_type)) 8110b57cec5SDimitry Andric return symbol; 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric return nullptr; 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric typedef struct { 8190b57cec5SDimitry Andric const Symtab *symtab; 8200b57cec5SDimitry Andric const addr_t file_addr; 8210b57cec5SDimitry Andric Symbol *match_symbol; 8220b57cec5SDimitry Andric const uint32_t *match_index_ptr; 8230b57cec5SDimitry Andric addr_t match_offset; 8240b57cec5SDimitry Andric } SymbolSearchInfo; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // Add all the section file start address & size to the RangeVector, recusively 8270b57cec5SDimitry Andric // adding any children sections. 8280b57cec5SDimitry Andric static void AddSectionsToRangeMap(SectionList *sectlist, 8290b57cec5SDimitry Andric RangeVector<addr_t, addr_t> §ion_ranges) { 8300b57cec5SDimitry Andric const int num_sections = sectlist->GetNumSections(0); 8310b57cec5SDimitry Andric for (int i = 0; i < num_sections; i++) { 8320b57cec5SDimitry Andric SectionSP sect_sp = sectlist->GetSectionAtIndex(i); 8330b57cec5SDimitry Andric if (sect_sp) { 8340b57cec5SDimitry Andric SectionList &child_sectlist = sect_sp->GetChildren(); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // If this section has children, add the children to the RangeVector. 8370b57cec5SDimitry Andric // Else add this section to the RangeVector. 8380b57cec5SDimitry Andric if (child_sectlist.GetNumSections(0) > 0) { 8390b57cec5SDimitry Andric AddSectionsToRangeMap(&child_sectlist, section_ranges); 8400b57cec5SDimitry Andric } else { 8410b57cec5SDimitry Andric size_t size = sect_sp->GetByteSize(); 8420b57cec5SDimitry Andric if (size > 0) { 8430b57cec5SDimitry Andric addr_t base_addr = sect_sp->GetFileAddress(); 8440b57cec5SDimitry Andric RangeVector<addr_t, addr_t>::Entry entry; 8450b57cec5SDimitry Andric entry.SetRangeBase(base_addr); 8460b57cec5SDimitry Andric entry.SetByteSize(size); 8470b57cec5SDimitry Andric section_ranges.Append(entry); 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric void Symtab::InitAddressIndexes() { 8550b57cec5SDimitry Andric // Protected function, no need to lock mutex... 8560b57cec5SDimitry Andric if (!m_file_addr_to_index_computed && !m_symbols.empty()) { 8570b57cec5SDimitry Andric m_file_addr_to_index_computed = true; 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric FileRangeToIndexMap::Entry entry; 8600b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 8610b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 8620b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 8630b57cec5SDimitry Andric if (pos->ValueIsAddress()) { 8640b57cec5SDimitry Andric entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); 8650b57cec5SDimitry Andric entry.SetByteSize(pos->GetByteSize()); 8660b57cec5SDimitry Andric entry.data = std::distance(begin, pos); 8670b57cec5SDimitry Andric m_file_addr_to_index.Append(entry); 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 8710b57cec5SDimitry Andric if (num_entries > 0) { 8720b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric // Create a RangeVector with the start & size of all the sections for 8750b57cec5SDimitry Andric // this objfile. We'll need to check this for any FileRangeToIndexMap 8760b57cec5SDimitry Andric // entries with an uninitialized size, which could potentially be a large 8770b57cec5SDimitry Andric // number so reconstituting the weak pointer is busywork when it is 8780b57cec5SDimitry Andric // invariant information. 8790b57cec5SDimitry Andric SectionList *sectlist = m_objfile->GetSectionList(); 8800b57cec5SDimitry Andric RangeVector<addr_t, addr_t> section_ranges; 8810b57cec5SDimitry Andric if (sectlist) { 8820b57cec5SDimitry Andric AddSectionsToRangeMap(sectlist, section_ranges); 8830b57cec5SDimitry Andric section_ranges.Sort(); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric // Iterate through the FileRangeToIndexMap and fill in the size for any 8870b57cec5SDimitry Andric // entries that didn't already have a size from the Symbol (e.g. if we 8880b57cec5SDimitry Andric // have a plain linker symbol with an address only, instead of debug info 8890b57cec5SDimitry Andric // where we get an address and a size and a type, etc.) 8900b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; i++) { 8910b57cec5SDimitry Andric FileRangeToIndexMap::Entry *entry = 8920b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(i); 893c14a5a88SDimitry Andric if (entry->GetByteSize() == 0) { 8940b57cec5SDimitry Andric addr_t curr_base_addr = entry->GetRangeBase(); 8950b57cec5SDimitry Andric const RangeVector<addr_t, addr_t>::Entry *containing_section = 8960b57cec5SDimitry Andric section_ranges.FindEntryThatContains(curr_base_addr); 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric // Use the end of the section as the default max size of the symbol 8990b57cec5SDimitry Andric addr_t sym_size = 0; 9000b57cec5SDimitry Andric if (containing_section) { 9010b57cec5SDimitry Andric sym_size = 9020b57cec5SDimitry Andric containing_section->GetByteSize() - 9030b57cec5SDimitry Andric (entry->GetRangeBase() - containing_section->GetRangeBase()); 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric for (size_t j = i; j < num_entries; j++) { 9070b57cec5SDimitry Andric FileRangeToIndexMap::Entry *next_entry = 9080b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(j); 9090b57cec5SDimitry Andric addr_t next_base_addr = next_entry->GetRangeBase(); 9100b57cec5SDimitry Andric if (next_base_addr > curr_base_addr) { 9110b57cec5SDimitry Andric addr_t size_to_next_symbol = next_base_addr - curr_base_addr; 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric // Take the difference between this symbol and the next one as 9140b57cec5SDimitry Andric // its size, if it is less than the size of the section. 9150b57cec5SDimitry Andric if (sym_size == 0 || size_to_next_symbol < sym_size) { 9160b57cec5SDimitry Andric sym_size = size_to_next_symbol; 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric break; 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric if (sym_size > 0) { 9230b57cec5SDimitry Andric entry->SetByteSize(sym_size); 9240b57cec5SDimitry Andric Symbol &symbol = m_symbols[entry->data]; 9250b57cec5SDimitry Andric symbol.SetByteSize(sym_size); 9260b57cec5SDimitry Andric symbol.SetSizeIsSynthesized(true); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric // Sort again in case the range size changes the ordering 9320b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric void Symtab::CalculateSymbolSizes() { 9380b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 9390b57cec5SDimitry Andric // Size computation happens inside InitAddressIndexes. 9400b57cec5SDimitry Andric InitAddressIndexes(); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { 9440b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 9450b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 9460b57cec5SDimitry Andric InitAddressIndexes(); 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 9490b57cec5SDimitry Andric m_file_addr_to_index.FindEntryStartsAt(file_addr); 9500b57cec5SDimitry Andric if (entry) { 9510b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 9520b57cec5SDimitry Andric if (symbol->GetFileAddress() == file_addr) 9530b57cec5SDimitry Andric return symbol; 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric return nullptr; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { 9590b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 9620b57cec5SDimitry Andric InitAddressIndexes(); 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 9650b57cec5SDimitry Andric m_file_addr_to_index.FindEntryThatContains(file_addr); 9660b57cec5SDimitry Andric if (entry) { 9670b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 9680b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) 9690b57cec5SDimitry Andric return symbol; 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric return nullptr; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric void Symtab::ForEachSymbolContainingFileAddress( 9750b57cec5SDimitry Andric addr_t file_addr, std::function<bool(Symbol *)> const &callback) { 9760b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 9790b57cec5SDimitry Andric InitAddressIndexes(); 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric std::vector<uint32_t> all_addr_indexes; 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric // Get all symbols with file_addr 9840b57cec5SDimitry Andric const size_t addr_match_count = 9850b57cec5SDimitry Andric m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, 9860b57cec5SDimitry Andric all_addr_indexes); 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric for (size_t i = 0; i < addr_match_count; ++i) { 9890b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); 9900b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) { 9910b57cec5SDimitry Andric if (!callback(symbol)) 9920b57cec5SDimitry Andric break; 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric void Symtab::SymbolIndicesToSymbolContextList( 9980b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { 9990b57cec5SDimitry Andric // No need to protect this call using m_mutex all other method calls are 10000b57cec5SDimitry Andric // already thread safe. 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric const bool merge_symbol_into_function = true; 10030b57cec5SDimitry Andric size_t num_indices = symbol_indexes.size(); 10040b57cec5SDimitry Andric if (num_indices > 0) { 10050b57cec5SDimitry Andric SymbolContext sc; 10060b57cec5SDimitry Andric sc.module_sp = m_objfile->GetModule(); 10070b57cec5SDimitry Andric for (size_t i = 0; i < num_indices; i++) { 10080b57cec5SDimitry Andric sc.symbol = SymbolAtIndex(symbol_indexes[i]); 10090b57cec5SDimitry Andric if (sc.symbol) 10100b57cec5SDimitry Andric sc_list.AppendIfUnique(sc, merge_symbol_into_function); 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 10159dba64beSDimitry Andric void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, 10160b57cec5SDimitry Andric SymbolContextList &sc_list) { 10170b57cec5SDimitry Andric std::vector<uint32_t> symbol_indexes; 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric // eFunctionNameTypeAuto should be pre-resolved by a call to 10200b57cec5SDimitry Andric // Module::LookupInfo::LookupInfo() 10210b57cec5SDimitry Andric assert((name_type_mask & eFunctionNameTypeAuto) == 0); 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { 10240b57cec5SDimitry Andric std::vector<uint32_t> temp_symbol_indexes; 10250b57cec5SDimitry Andric FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 10280b57cec5SDimitry Andric if (temp_symbol_indexes_size > 0) { 10290b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10300b57cec5SDimitry Andric for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { 10310b57cec5SDimitry Andric SymbolContext sym_ctx; 10320b57cec5SDimitry Andric sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); 10330b57cec5SDimitry Andric if (sym_ctx.symbol) { 10340b57cec5SDimitry Andric switch (sym_ctx.symbol->GetType()) { 10350b57cec5SDimitry Andric case eSymbolTypeCode: 10360b57cec5SDimitry Andric case eSymbolTypeResolver: 10370b57cec5SDimitry Andric case eSymbolTypeReExported: 10380b57cec5SDimitry Andric symbol_indexes.push_back(temp_symbol_indexes[i]); 10390b57cec5SDimitry Andric break; 10400b57cec5SDimitry Andric default: 10410b57cec5SDimitry Andric break; 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeBase) { 10490b57cec5SDimitry Andric // From mangled names we can't tell what is a basename and what is a method 10500b57cec5SDimitry Andric // name, so we just treat them the same 10510b57cec5SDimitry Andric if (!m_name_indexes_computed) 10520b57cec5SDimitry Andric InitNameIndexes(); 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric if (!m_basename_to_index.IsEmpty()) { 10550b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 10560b57cec5SDimitry Andric for (match = m_basename_to_index.FindFirstValueForName(name); 10570b57cec5SDimitry Andric match != nullptr; 10580b57cec5SDimitry Andric match = m_basename_to_index.FindNextValueForName(match)) { 10590b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeMethod) { 10650b57cec5SDimitry Andric if (!m_name_indexes_computed) 10660b57cec5SDimitry Andric InitNameIndexes(); 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric if (!m_method_to_index.IsEmpty()) { 10690b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 10700b57cec5SDimitry Andric for (match = m_method_to_index.FindFirstValueForName(name); 10710b57cec5SDimitry Andric match != nullptr; 10720b57cec5SDimitry Andric match = m_method_to_index.FindNextValueForName(match)) { 10730b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeSelector) { 10790b57cec5SDimitry Andric if (!m_name_indexes_computed) 10800b57cec5SDimitry Andric InitNameIndexes(); 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric if (!m_selector_to_index.IsEmpty()) { 10830b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 10840b57cec5SDimitry Andric for (match = m_selector_to_index.FindFirstValueForName(name); 10850b57cec5SDimitry Andric match != nullptr; 10860b57cec5SDimitry Andric match = m_selector_to_index.FindNextValueForName(match)) { 10870b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric } 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric if (!symbol_indexes.empty()) { 10930b57cec5SDimitry Andric llvm::sort(symbol_indexes.begin(), symbol_indexes.end()); 10940b57cec5SDimitry Andric symbol_indexes.erase( 10950b57cec5SDimitry Andric std::unique(symbol_indexes.begin(), symbol_indexes.end()), 10960b57cec5SDimitry Andric symbol_indexes.end()); 10970b57cec5SDimitry Andric SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); 10980b57cec5SDimitry Andric } 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric const Symbol *Symtab::GetParent(Symbol *child_symbol) const { 11020b57cec5SDimitry Andric uint32_t child_idx = GetIndexForSymbol(child_symbol); 11030b57cec5SDimitry Andric if (child_idx != UINT32_MAX && child_idx > 0) { 11040b57cec5SDimitry Andric for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { 11050b57cec5SDimitry Andric const Symbol *symbol = SymbolAtIndex(idx); 11060b57cec5SDimitry Andric const uint32_t sibling_idx = symbol->GetSiblingIndex(); 11070b57cec5SDimitry Andric if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) 11080b57cec5SDimitry Andric return symbol; 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric return nullptr; 11120b57cec5SDimitry Andric } 1113