1*0b57cec5SDimitry Andric //===-- Symtab.cpp ----------------------------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include <map> 10*0b57cec5SDimitry Andric #include <set> 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "Plugins/Language/ObjC/ObjCLanguage.h" 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "lldb/Core/Module.h" 15*0b57cec5SDimitry Andric #include "lldb/Core/RichManglingContext.h" 16*0b57cec5SDimitry Andric #include "lldb/Core/STLUtils.h" 17*0b57cec5SDimitry Andric #include "lldb/Core/Section.h" 18*0b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 19*0b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h" 20*0b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 21*0b57cec5SDimitry Andric #include "lldb/Symbol/Symtab.h" 22*0b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h" 23*0b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 24*0b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric using namespace lldb; 29*0b57cec5SDimitry Andric using namespace lldb_private; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric Symtab::Symtab(ObjectFile *objfile) 32*0b57cec5SDimitry Andric : m_objfile(objfile), m_symbols(), m_file_addr_to_index(), 33*0b57cec5SDimitry Andric m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false), 34*0b57cec5SDimitry Andric m_name_indexes_computed(false) {} 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric Symtab::~Symtab() {} 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric void Symtab::Reserve(size_t count) { 39*0b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 40*0b57cec5SDimitry Andric // when calling this function to avoid performance issues. 41*0b57cec5SDimitry Andric m_symbols.reserve(count); 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric Symbol *Symtab::Resize(size_t count) { 45*0b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 46*0b57cec5SDimitry Andric // when calling this function to avoid performance issues. 47*0b57cec5SDimitry Andric m_symbols.resize(count); 48*0b57cec5SDimitry Andric return m_symbols.empty() ? nullptr : &m_symbols[0]; 49*0b57cec5SDimitry Andric } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric uint32_t Symtab::AddSymbol(const Symbol &symbol) { 52*0b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 53*0b57cec5SDimitry Andric // when calling this function to avoid performance issues. 54*0b57cec5SDimitry Andric uint32_t symbol_idx = m_symbols.size(); 55*0b57cec5SDimitry Andric m_name_to_index.Clear(); 56*0b57cec5SDimitry Andric m_file_addr_to_index.Clear(); 57*0b57cec5SDimitry Andric m_symbols.push_back(symbol); 58*0b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 59*0b57cec5SDimitry Andric m_name_indexes_computed = false; 60*0b57cec5SDimitry Andric return symbol_idx; 61*0b57cec5SDimitry Andric } 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric size_t Symtab::GetNumSymbols() const { 64*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 65*0b57cec5SDimitry Andric return m_symbols.size(); 66*0b57cec5SDimitry Andric } 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric void Symtab::SectionFileAddressesChanged() { 69*0b57cec5SDimitry Andric m_name_to_index.Clear(); 70*0b57cec5SDimitry Andric m_file_addr_to_index_computed = false; 71*0b57cec5SDimitry Andric } 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) { 74*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 77*0b57cec5SDimitry Andric s->Indent(); 78*0b57cec5SDimitry Andric const FileSpec &file_spec = m_objfile->GetFileSpec(); 79*0b57cec5SDimitry Andric const char *object_name = nullptr; 80*0b57cec5SDimitry Andric if (m_objfile->GetModule()) 81*0b57cec5SDimitry Andric object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric if (file_spec) 84*0b57cec5SDimitry Andric s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, 85*0b57cec5SDimitry Andric file_spec.GetPath().c_str(), object_name ? "(" : "", 86*0b57cec5SDimitry Andric object_name ? object_name : "", object_name ? ")" : "", 87*0b57cec5SDimitry Andric (uint64_t)m_symbols.size()); 88*0b57cec5SDimitry Andric else 89*0b57cec5SDimitry Andric s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric if (!m_symbols.empty()) { 92*0b57cec5SDimitry Andric switch (sort_order) { 93*0b57cec5SDimitry Andric case eSortOrderNone: { 94*0b57cec5SDimitry Andric s->PutCString(":\n"); 95*0b57cec5SDimitry Andric DumpSymbolHeader(s); 96*0b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 97*0b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 98*0b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 99*0b57cec5SDimitry Andric s->Indent(); 100*0b57cec5SDimitry Andric pos->Dump(s, target, std::distance(begin, pos)); 101*0b57cec5SDimitry Andric } 102*0b57cec5SDimitry Andric } break; 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric case eSortOrderByName: { 105*0b57cec5SDimitry Andric // Although we maintain a lookup by exact name map, the table isn't 106*0b57cec5SDimitry Andric // sorted by name. So we must make the ordered symbol list up ourselves. 107*0b57cec5SDimitry Andric s->PutCString(" (sorted by name):\n"); 108*0b57cec5SDimitry Andric DumpSymbolHeader(s); 109*0b57cec5SDimitry Andric typedef std::multimap<const char *, const Symbol *, 110*0b57cec5SDimitry Andric CStringCompareFunctionObject> 111*0b57cec5SDimitry Andric CStringToSymbol; 112*0b57cec5SDimitry Andric CStringToSymbol name_map; 113*0b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 114*0b57cec5SDimitry Andric pos != end; ++pos) { 115*0b57cec5SDimitry Andric const char *name = pos->GetName().AsCString(); 116*0b57cec5SDimitry Andric if (name && name[0]) 117*0b57cec5SDimitry Andric name_map.insert(std::make_pair(name, &(*pos))); 118*0b57cec5SDimitry Andric } 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric for (CStringToSymbol::const_iterator pos = name_map.begin(), 121*0b57cec5SDimitry Andric end = name_map.end(); 122*0b57cec5SDimitry Andric pos != end; ++pos) { 123*0b57cec5SDimitry Andric s->Indent(); 124*0b57cec5SDimitry Andric pos->second->Dump(s, target, pos->second - &m_symbols[0]); 125*0b57cec5SDimitry Andric } 126*0b57cec5SDimitry Andric } break; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric case eSortOrderByAddress: 129*0b57cec5SDimitry Andric s->PutCString(" (sorted by address):\n"); 130*0b57cec5SDimitry Andric DumpSymbolHeader(s); 131*0b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 132*0b57cec5SDimitry Andric InitAddressIndexes(); 133*0b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 134*0b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; ++i) { 135*0b57cec5SDimitry Andric s->Indent(); 136*0b57cec5SDimitry Andric const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; 137*0b57cec5SDimitry Andric m_symbols[symbol_idx].Dump(s, target, symbol_idx); 138*0b57cec5SDimitry Andric } 139*0b57cec5SDimitry Andric break; 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric } else { 142*0b57cec5SDimitry Andric s->PutCString("\n"); 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric void Symtab::Dump(Stream *s, Target *target, 147*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) const { 148*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric const size_t num_symbols = GetNumSymbols(); 151*0b57cec5SDimitry Andric // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 152*0b57cec5SDimitry Andric s->Indent(); 153*0b57cec5SDimitry Andric s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", 154*0b57cec5SDimitry Andric (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); 155*0b57cec5SDimitry Andric s->IndentMore(); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric if (!indexes.empty()) { 158*0b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos; 159*0b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator end = indexes.end(); 160*0b57cec5SDimitry Andric DumpSymbolHeader(s); 161*0b57cec5SDimitry Andric for (pos = indexes.begin(); pos != end; ++pos) { 162*0b57cec5SDimitry Andric size_t idx = *pos; 163*0b57cec5SDimitry Andric if (idx < num_symbols) { 164*0b57cec5SDimitry Andric s->Indent(); 165*0b57cec5SDimitry Andric m_symbols[idx].Dump(s, target, idx); 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric } 168*0b57cec5SDimitry Andric } 169*0b57cec5SDimitry Andric s->IndentLess(); 170*0b57cec5SDimitry Andric } 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric void Symtab::DumpSymbolHeader(Stream *s) { 173*0b57cec5SDimitry Andric s->Indent(" Debug symbol\n"); 174*0b57cec5SDimitry Andric s->Indent(" |Synthetic symbol\n"); 175*0b57cec5SDimitry Andric s->Indent(" ||Externally Visible\n"); 176*0b57cec5SDimitry Andric s->Indent(" |||\n"); 177*0b57cec5SDimitry Andric s->Indent("Index UserID DSX Type File Address/Value Load " 178*0b57cec5SDimitry Andric "Address Size Flags Name\n"); 179*0b57cec5SDimitry Andric s->Indent("------- ------ --- --------------- ------------------ " 180*0b57cec5SDimitry Andric "------------------ ------------------ ---------- " 181*0b57cec5SDimitry Andric "----------------------------------\n"); 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric static int CompareSymbolID(const void *key, const void *p) { 185*0b57cec5SDimitry Andric const user_id_t match_uid = *(const user_id_t *)key; 186*0b57cec5SDimitry Andric const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); 187*0b57cec5SDimitry Andric if (match_uid < symbol_uid) 188*0b57cec5SDimitry Andric return -1; 189*0b57cec5SDimitry Andric if (match_uid > symbol_uid) 190*0b57cec5SDimitry Andric return 1; 191*0b57cec5SDimitry Andric return 0; 192*0b57cec5SDimitry Andric } 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andric Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const { 195*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric Symbol *symbol = 198*0b57cec5SDimitry Andric (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(), 199*0b57cec5SDimitry Andric sizeof(m_symbols[0]), CompareSymbolID); 200*0b57cec5SDimitry Andric return symbol; 201*0b57cec5SDimitry Andric } 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric Symbol *Symtab::SymbolAtIndex(size_t idx) { 204*0b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 205*0b57cec5SDimitry Andric // when calling this function to avoid performance issues. 206*0b57cec5SDimitry Andric if (idx < m_symbols.size()) 207*0b57cec5SDimitry Andric return &m_symbols[idx]; 208*0b57cec5SDimitry Andric return nullptr; 209*0b57cec5SDimitry Andric } 210*0b57cec5SDimitry Andric 211*0b57cec5SDimitry Andric const Symbol *Symtab::SymbolAtIndex(size_t idx) const { 212*0b57cec5SDimitry Andric // Clients should grab the mutex from this symbol table and lock it manually 213*0b57cec5SDimitry Andric // when calling this function to avoid performance issues. 214*0b57cec5SDimitry Andric if (idx < m_symbols.size()) 215*0b57cec5SDimitry Andric return &m_symbols[idx]; 216*0b57cec5SDimitry Andric return nullptr; 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric static bool lldb_skip_name(llvm::StringRef mangled, 220*0b57cec5SDimitry Andric Mangled::ManglingScheme scheme) { 221*0b57cec5SDimitry Andric switch (scheme) { 222*0b57cec5SDimitry Andric case Mangled::eManglingSchemeItanium: { 223*0b57cec5SDimitry Andric if (mangled.size() < 3 || !mangled.startswith("_Z")) 224*0b57cec5SDimitry Andric return true; 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric // Avoid the following types of symbols in the index. 227*0b57cec5SDimitry Andric switch (mangled[2]) { 228*0b57cec5SDimitry Andric case 'G': // guard variables 229*0b57cec5SDimitry Andric case 'T': // virtual tables, VTT structures, typeinfo structures + names 230*0b57cec5SDimitry Andric case 'Z': // named local entities (if we eventually handle 231*0b57cec5SDimitry Andric // eSymbolTypeData, we will want this back) 232*0b57cec5SDimitry Andric return true; 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric default: 235*0b57cec5SDimitry Andric break; 236*0b57cec5SDimitry Andric } 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric // Include this name in the index. 239*0b57cec5SDimitry Andric return false; 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric // No filters for this scheme yet. Include all names in indexing. 243*0b57cec5SDimitry Andric case Mangled::eManglingSchemeMSVC: 244*0b57cec5SDimitry Andric return false; 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric // Don't try and demangle things we can't categorize. 247*0b57cec5SDimitry Andric case Mangled::eManglingSchemeNone: 248*0b57cec5SDimitry Andric return true; 249*0b57cec5SDimitry Andric } 250*0b57cec5SDimitry Andric llvm_unreachable("unknown scheme!"); 251*0b57cec5SDimitry Andric } 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric void Symtab::InitNameIndexes() { 254*0b57cec5SDimitry Andric // Protected function, no need to lock mutex... 255*0b57cec5SDimitry Andric if (!m_name_indexes_computed) { 256*0b57cec5SDimitry Andric m_name_indexes_computed = true; 257*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 258*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 259*0b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 260*0b57cec5SDimitry Andric const size_t num_symbols = m_symbols.size(); 261*0b57cec5SDimitry Andric m_name_to_index.Reserve(num_symbols); 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric // The "const char *" in "class_contexts" and backlog::value_type::second 264*0b57cec5SDimitry Andric // must come from a ConstString::GetCString() 265*0b57cec5SDimitry Andric std::set<const char *> class_contexts; 266*0b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog; 267*0b57cec5SDimitry Andric backlog.reserve(num_symbols / 2); 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andric // Instantiation of the demangler is expensive, so better use a single one 270*0b57cec5SDimitry Andric // for all entries during batch processing. 271*0b57cec5SDimitry Andric RichManglingContext rmc; 272*0b57cec5SDimitry Andric for (uint32_t value = 0; value < num_symbols; ++value) { 273*0b57cec5SDimitry Andric Symbol *symbol = &m_symbols[value]; 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric // Don't let trampolines get into the lookup by name map If we ever need 276*0b57cec5SDimitry Andric // the trampoline symbols to be searchable by name we can remove this and 277*0b57cec5SDimitry Andric // then possibly add a new bool to any of the Symtab functions that 278*0b57cec5SDimitry Andric // lookup symbols by name to indicate if they want trampolines. 279*0b57cec5SDimitry Andric if (symbol->IsTrampoline()) 280*0b57cec5SDimitry Andric continue; 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric // If the symbol's name string matched a Mangled::ManglingScheme, it is 283*0b57cec5SDimitry Andric // stored in the mangled field. 284*0b57cec5SDimitry Andric Mangled &mangled = symbol->GetMangled(); 285*0b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) { 286*0b57cec5SDimitry Andric m_name_to_index.Append(name, value); 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 289*0b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 290*0b57cec5SDimitry Andric // the annotations. 291*0b57cec5SDimitry Andric ConstString stripped = ConstString( 292*0b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 293*0b57cec5SDimitry Andric m_name_to_index.Append(stripped, value); 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric const SymbolType type = symbol->GetType(); 297*0b57cec5SDimitry Andric if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { 298*0b57cec5SDimitry Andric if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name)) 299*0b57cec5SDimitry Andric RegisterMangledNameEntry(value, class_contexts, backlog, rmc); 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric } 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric // Symbol name strings that didn't match a Mangled::ManglingScheme, are 304*0b57cec5SDimitry Andric // stored in the demangled field. 305*0b57cec5SDimitry Andric if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) { 306*0b57cec5SDimitry Andric m_name_to_index.Append(name, value); 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric if (symbol->ContainsLinkerAnnotations()) { 309*0b57cec5SDimitry Andric // If the symbol has linker annotations, also add the version without 310*0b57cec5SDimitry Andric // the annotations. 311*0b57cec5SDimitry Andric name = ConstString( 312*0b57cec5SDimitry Andric m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef())); 313*0b57cec5SDimitry Andric m_name_to_index.Append(name, value); 314*0b57cec5SDimitry Andric } 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric // If the demangled name turns out to be an ObjC name, and is a category 317*0b57cec5SDimitry Andric // name, add the version without categories to the index too. 318*0b57cec5SDimitry Andric ObjCLanguage::MethodName objc_method(name.GetStringRef(), true); 319*0b57cec5SDimitry Andric if (objc_method.IsValid(true)) { 320*0b57cec5SDimitry Andric m_selector_to_index.Append(objc_method.GetSelector(), value); 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric if (ConstString objc_method_no_category = 323*0b57cec5SDimitry Andric objc_method.GetFullNameWithoutCategory(true)) 324*0b57cec5SDimitry Andric m_name_to_index.Append(objc_method_no_category, value); 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric } 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric for (const auto &record : backlog) { 330*0b57cec5SDimitry Andric RegisterBacklogEntry(record.first, record.second, class_contexts); 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric m_name_to_index.Sort(); 334*0b57cec5SDimitry Andric m_name_to_index.SizeToFit(); 335*0b57cec5SDimitry Andric m_selector_to_index.Sort(); 336*0b57cec5SDimitry Andric m_selector_to_index.SizeToFit(); 337*0b57cec5SDimitry Andric m_basename_to_index.Sort(); 338*0b57cec5SDimitry Andric m_basename_to_index.SizeToFit(); 339*0b57cec5SDimitry Andric m_method_to_index.Sort(); 340*0b57cec5SDimitry Andric m_method_to_index.SizeToFit(); 341*0b57cec5SDimitry Andric } 342*0b57cec5SDimitry Andric } 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric void Symtab::RegisterMangledNameEntry( 345*0b57cec5SDimitry Andric uint32_t value, std::set<const char *> &class_contexts, 346*0b57cec5SDimitry Andric std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, 347*0b57cec5SDimitry Andric RichManglingContext &rmc) { 348*0b57cec5SDimitry Andric // Only register functions that have a base name. 349*0b57cec5SDimitry Andric rmc.ParseFunctionBaseName(); 350*0b57cec5SDimitry Andric llvm::StringRef base_name = rmc.GetBufferRef(); 351*0b57cec5SDimitry Andric if (base_name.empty()) 352*0b57cec5SDimitry Andric return; 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric // The base name will be our entry's name. 355*0b57cec5SDimitry Andric NameToIndexMap::Entry entry(ConstString(base_name), value); 356*0b57cec5SDimitry Andric 357*0b57cec5SDimitry Andric rmc.ParseFunctionDeclContextName(); 358*0b57cec5SDimitry Andric llvm::StringRef decl_context = rmc.GetBufferRef(); 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric // Register functions with no context. 361*0b57cec5SDimitry Andric if (decl_context.empty()) { 362*0b57cec5SDimitry Andric // This has to be a basename 363*0b57cec5SDimitry Andric m_basename_to_index.Append(entry); 364*0b57cec5SDimitry Andric // If there is no context (no namespaces or class scopes that come before 365*0b57cec5SDimitry Andric // the function name) then this also could be a fullname. 366*0b57cec5SDimitry Andric m_name_to_index.Append(entry); 367*0b57cec5SDimitry Andric return; 368*0b57cec5SDimitry Andric } 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric // Make sure we have a pool-string pointer and see if we already know the 371*0b57cec5SDimitry Andric // context name. 372*0b57cec5SDimitry Andric const char *decl_context_ccstr = ConstString(decl_context).GetCString(); 373*0b57cec5SDimitry Andric auto it = class_contexts.find(decl_context_ccstr); 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric // Register constructors and destructors. They are methods and create 376*0b57cec5SDimitry Andric // declaration contexts. 377*0b57cec5SDimitry Andric if (rmc.IsCtorOrDtor()) { 378*0b57cec5SDimitry Andric m_method_to_index.Append(entry); 379*0b57cec5SDimitry Andric if (it == class_contexts.end()) 380*0b57cec5SDimitry Andric class_contexts.insert(it, decl_context_ccstr); 381*0b57cec5SDimitry Andric return; 382*0b57cec5SDimitry Andric } 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric // Register regular methods with a known declaration context. 385*0b57cec5SDimitry Andric if (it != class_contexts.end()) { 386*0b57cec5SDimitry Andric m_method_to_index.Append(entry); 387*0b57cec5SDimitry Andric return; 388*0b57cec5SDimitry Andric } 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric // Regular methods in unknown declaration contexts are put to the backlog. We 391*0b57cec5SDimitry Andric // will revisit them once we processed all remaining symbols. 392*0b57cec5SDimitry Andric backlog.push_back(std::make_pair(entry, decl_context_ccstr)); 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric 395*0b57cec5SDimitry Andric void Symtab::RegisterBacklogEntry( 396*0b57cec5SDimitry Andric const NameToIndexMap::Entry &entry, const char *decl_context, 397*0b57cec5SDimitry Andric const std::set<const char *> &class_contexts) { 398*0b57cec5SDimitry Andric auto it = class_contexts.find(decl_context); 399*0b57cec5SDimitry Andric if (it != class_contexts.end()) { 400*0b57cec5SDimitry Andric m_method_to_index.Append(entry); 401*0b57cec5SDimitry Andric } else { 402*0b57cec5SDimitry Andric // If we got here, we have something that had a context (was inside 403*0b57cec5SDimitry Andric // a namespace or class) yet we don't know the entry 404*0b57cec5SDimitry Andric m_method_to_index.Append(entry); 405*0b57cec5SDimitry Andric m_basename_to_index.Append(entry); 406*0b57cec5SDimitry Andric } 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric void Symtab::PreloadSymbols() { 410*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 411*0b57cec5SDimitry Andric InitNameIndexes(); 412*0b57cec5SDimitry Andric } 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, 415*0b57cec5SDimitry Andric bool add_demangled, bool add_mangled, 416*0b57cec5SDimitry Andric NameToIndexMap &name_to_index_map) const { 417*0b57cec5SDimitry Andric if (add_demangled || add_mangled) { 418*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 419*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 420*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 421*0b57cec5SDimitry Andric 422*0b57cec5SDimitry Andric // Create the name index vector to be able to quickly search by name 423*0b57cec5SDimitry Andric const size_t num_indexes = indexes.size(); 424*0b57cec5SDimitry Andric for (size_t i = 0; i < num_indexes; ++i) { 425*0b57cec5SDimitry Andric uint32_t value = indexes[i]; 426*0b57cec5SDimitry Andric assert(i < m_symbols.size()); 427*0b57cec5SDimitry Andric const Symbol *symbol = &m_symbols[value]; 428*0b57cec5SDimitry Andric 429*0b57cec5SDimitry Andric const Mangled &mangled = symbol->GetMangled(); 430*0b57cec5SDimitry Andric if (add_demangled) { 431*0b57cec5SDimitry Andric if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) 432*0b57cec5SDimitry Andric name_to_index_map.Append(name, value); 433*0b57cec5SDimitry Andric } 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric if (add_mangled) { 436*0b57cec5SDimitry Andric if (ConstString name = mangled.GetMangledName()) 437*0b57cec5SDimitry Andric name_to_index_map.Append(name, value); 438*0b57cec5SDimitry Andric } 439*0b57cec5SDimitry Andric } 440*0b57cec5SDimitry Andric } 441*0b57cec5SDimitry Andric } 442*0b57cec5SDimitry Andric 443*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 444*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 445*0b57cec5SDimitry Andric uint32_t start_idx, 446*0b57cec5SDimitry Andric uint32_t end_index) const { 447*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 448*0b57cec5SDimitry Andric 449*0b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 454*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 455*0b57cec5SDimitry Andric indexes.push_back(i); 456*0b57cec5SDimitry Andric } 457*0b57cec5SDimitry Andric 458*0b57cec5SDimitry Andric return indexes.size() - prev_size; 459*0b57cec5SDimitry Andric } 460*0b57cec5SDimitry Andric 461*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue( 462*0b57cec5SDimitry Andric SymbolType symbol_type, uint32_t flags_value, 463*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes, uint32_t start_idx, 464*0b57cec5SDimitry Andric uint32_t end_index) const { 465*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 466*0b57cec5SDimitry Andric 467*0b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 468*0b57cec5SDimitry Andric 469*0b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 470*0b57cec5SDimitry Andric 471*0b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 472*0b57cec5SDimitry Andric if ((symbol_type == eSymbolTypeAny || 473*0b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) && 474*0b57cec5SDimitry Andric m_symbols[i].GetFlags() == flags_value) 475*0b57cec5SDimitry Andric indexes.push_back(i); 476*0b57cec5SDimitry Andric } 477*0b57cec5SDimitry Andric 478*0b57cec5SDimitry Andric return indexes.size() - prev_size; 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 482*0b57cec5SDimitry Andric Debug symbol_debug_type, 483*0b57cec5SDimitry Andric Visibility symbol_visibility, 484*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes, 485*0b57cec5SDimitry Andric uint32_t start_idx, 486*0b57cec5SDimitry Andric uint32_t end_index) const { 487*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 488*0b57cec5SDimitry Andric 489*0b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 490*0b57cec5SDimitry Andric 491*0b57cec5SDimitry Andric const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric for (uint32_t i = start_idx; i < count; ++i) { 494*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 495*0b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 496*0b57cec5SDimitry Andric if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 497*0b57cec5SDimitry Andric indexes.push_back(i); 498*0b57cec5SDimitry Andric } 499*0b57cec5SDimitry Andric } 500*0b57cec5SDimitry Andric 501*0b57cec5SDimitry Andric return indexes.size() - prev_size; 502*0b57cec5SDimitry Andric } 503*0b57cec5SDimitry Andric 504*0b57cec5SDimitry Andric uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const { 505*0b57cec5SDimitry Andric if (!m_symbols.empty()) { 506*0b57cec5SDimitry Andric const Symbol *first_symbol = &m_symbols[0]; 507*0b57cec5SDimitry Andric if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 508*0b57cec5SDimitry Andric return symbol - first_symbol; 509*0b57cec5SDimitry Andric } 510*0b57cec5SDimitry Andric return UINT32_MAX; 511*0b57cec5SDimitry Andric } 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andric struct SymbolSortInfo { 514*0b57cec5SDimitry Andric const bool sort_by_load_addr; 515*0b57cec5SDimitry Andric const Symbol *symbols; 516*0b57cec5SDimitry Andric }; 517*0b57cec5SDimitry Andric 518*0b57cec5SDimitry Andric namespace { 519*0b57cec5SDimitry Andric struct SymbolIndexComparator { 520*0b57cec5SDimitry Andric const std::vector<Symbol> &symbols; 521*0b57cec5SDimitry Andric std::vector<lldb::addr_t> &addr_cache; 522*0b57cec5SDimitry Andric 523*0b57cec5SDimitry Andric // Getting from the symbol to the Address to the File Address involves some 524*0b57cec5SDimitry Andric // work. Since there are potentially many symbols here, and we're using this 525*0b57cec5SDimitry Andric // for sorting so we're going to be computing the address many times, cache 526*0b57cec5SDimitry Andric // that in addr_cache. The array passed in has to be the same size as the 527*0b57cec5SDimitry Andric // symbols array passed into the member variable symbols, and should be 528*0b57cec5SDimitry Andric // initialized with LLDB_INVALID_ADDRESS. 529*0b57cec5SDimitry Andric // NOTE: You have to make addr_cache externally and pass it in because 530*0b57cec5SDimitry Andric // std::stable_sort 531*0b57cec5SDimitry Andric // makes copies of the comparator it is initially passed in, and you end up 532*0b57cec5SDimitry Andric // spending huge amounts of time copying this array... 533*0b57cec5SDimitry Andric 534*0b57cec5SDimitry Andric SymbolIndexComparator(const std::vector<Symbol> &s, 535*0b57cec5SDimitry Andric std::vector<lldb::addr_t> &a) 536*0b57cec5SDimitry Andric : symbols(s), addr_cache(a) { 537*0b57cec5SDimitry Andric assert(symbols.size() == addr_cache.size()); 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric bool operator()(uint32_t index_a, uint32_t index_b) { 540*0b57cec5SDimitry Andric addr_t value_a = addr_cache[index_a]; 541*0b57cec5SDimitry Andric if (value_a == LLDB_INVALID_ADDRESS) { 542*0b57cec5SDimitry Andric value_a = symbols[index_a].GetAddressRef().GetFileAddress(); 543*0b57cec5SDimitry Andric addr_cache[index_a] = value_a; 544*0b57cec5SDimitry Andric } 545*0b57cec5SDimitry Andric 546*0b57cec5SDimitry Andric addr_t value_b = addr_cache[index_b]; 547*0b57cec5SDimitry Andric if (value_b == LLDB_INVALID_ADDRESS) { 548*0b57cec5SDimitry Andric value_b = symbols[index_b].GetAddressRef().GetFileAddress(); 549*0b57cec5SDimitry Andric addr_cache[index_b] = value_b; 550*0b57cec5SDimitry Andric } 551*0b57cec5SDimitry Andric 552*0b57cec5SDimitry Andric if (value_a == value_b) { 553*0b57cec5SDimitry Andric // The if the values are equal, use the original symbol user ID 554*0b57cec5SDimitry Andric lldb::user_id_t uid_a = symbols[index_a].GetID(); 555*0b57cec5SDimitry Andric lldb::user_id_t uid_b = symbols[index_b].GetID(); 556*0b57cec5SDimitry Andric if (uid_a < uid_b) 557*0b57cec5SDimitry Andric return true; 558*0b57cec5SDimitry Andric if (uid_a > uid_b) 559*0b57cec5SDimitry Andric return false; 560*0b57cec5SDimitry Andric return false; 561*0b57cec5SDimitry Andric } else if (value_a < value_b) 562*0b57cec5SDimitry Andric return true; 563*0b57cec5SDimitry Andric 564*0b57cec5SDimitry Andric return false; 565*0b57cec5SDimitry Andric } 566*0b57cec5SDimitry Andric }; 567*0b57cec5SDimitry Andric } 568*0b57cec5SDimitry Andric 569*0b57cec5SDimitry Andric void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, 570*0b57cec5SDimitry Andric bool remove_duplicates) const { 571*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 572*0b57cec5SDimitry Andric 573*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 574*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 575*0b57cec5SDimitry Andric // No need to sort if we have zero or one items... 576*0b57cec5SDimitry Andric if (indexes.size() <= 1) 577*0b57cec5SDimitry Andric return; 578*0b57cec5SDimitry Andric 579*0b57cec5SDimitry Andric // Sort the indexes in place using std::stable_sort. 580*0b57cec5SDimitry Andric // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly 581*0b57cec5SDimitry Andric // for performance, not correctness. The indexes vector tends to be "close" 582*0b57cec5SDimitry Andric // to sorted, which the stable sort handles better. 583*0b57cec5SDimitry Andric 584*0b57cec5SDimitry Andric std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 585*0b57cec5SDimitry Andric 586*0b57cec5SDimitry Andric SymbolIndexComparator comparator(m_symbols, addr_cache); 587*0b57cec5SDimitry Andric std::stable_sort(indexes.begin(), indexes.end(), comparator); 588*0b57cec5SDimitry Andric 589*0b57cec5SDimitry Andric // Remove any duplicates if requested 590*0b57cec5SDimitry Andric if (remove_duplicates) { 591*0b57cec5SDimitry Andric auto last = std::unique(indexes.begin(), indexes.end()); 592*0b57cec5SDimitry Andric indexes.erase(last, indexes.end()); 593*0b57cec5SDimitry Andric } 594*0b57cec5SDimitry Andric } 595*0b57cec5SDimitry Andric 596*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 597*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 598*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 599*0b57cec5SDimitry Andric 600*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 601*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 602*0b57cec5SDimitry Andric if (symbol_name) { 603*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 604*0b57cec5SDimitry Andric InitNameIndexes(); 605*0b57cec5SDimitry Andric 606*0b57cec5SDimitry Andric return m_name_to_index.GetValues(symbol_name, indexes); 607*0b57cec5SDimitry Andric } 608*0b57cec5SDimitry Andric return 0; 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric 611*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, 612*0b57cec5SDimitry Andric Debug symbol_debug_type, 613*0b57cec5SDimitry Andric Visibility symbol_visibility, 614*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 615*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 616*0b57cec5SDimitry Andric 617*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 618*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 619*0b57cec5SDimitry Andric if (symbol_name) { 620*0b57cec5SDimitry Andric const size_t old_size = indexes.size(); 621*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 622*0b57cec5SDimitry Andric InitNameIndexes(); 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric std::vector<uint32_t> all_name_indexes; 625*0b57cec5SDimitry Andric const size_t name_match_count = 626*0b57cec5SDimitry Andric m_name_to_index.GetValues(symbol_name, all_name_indexes); 627*0b57cec5SDimitry Andric for (size_t i = 0; i < name_match_count; ++i) { 628*0b57cec5SDimitry Andric if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, 629*0b57cec5SDimitry Andric symbol_visibility)) 630*0b57cec5SDimitry Andric indexes.push_back(all_name_indexes[i]); 631*0b57cec5SDimitry Andric } 632*0b57cec5SDimitry Andric return indexes.size() - old_size; 633*0b57cec5SDimitry Andric } 634*0b57cec5SDimitry Andric return 0; 635*0b57cec5SDimitry Andric } 636*0b57cec5SDimitry Andric 637*0b57cec5SDimitry Andric uint32_t 638*0b57cec5SDimitry Andric Symtab::AppendSymbolIndexesWithNameAndType(ConstString symbol_name, 639*0b57cec5SDimitry Andric SymbolType symbol_type, 640*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 641*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 642*0b57cec5SDimitry Andric 643*0b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { 644*0b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 645*0b57cec5SDimitry Andric while (pos != indexes.end()) { 646*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 647*0b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 648*0b57cec5SDimitry Andric ++pos; 649*0b57cec5SDimitry Andric else 650*0b57cec5SDimitry Andric pos = indexes.erase(pos); 651*0b57cec5SDimitry Andric } 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric return indexes.size(); 654*0b57cec5SDimitry Andric } 655*0b57cec5SDimitry Andric 656*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 657*0b57cec5SDimitry Andric ConstString symbol_name, SymbolType symbol_type, 658*0b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 659*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 660*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, 663*0b57cec5SDimitry Andric symbol_visibility, indexes) > 0) { 664*0b57cec5SDimitry Andric std::vector<uint32_t>::iterator pos = indexes.begin(); 665*0b57cec5SDimitry Andric while (pos != indexes.end()) { 666*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 667*0b57cec5SDimitry Andric m_symbols[*pos].GetType() == symbol_type) 668*0b57cec5SDimitry Andric ++pos; 669*0b57cec5SDimitry Andric else 670*0b57cec5SDimitry Andric pos = indexes.erase(pos); 671*0b57cec5SDimitry Andric } 672*0b57cec5SDimitry Andric } 673*0b57cec5SDimitry Andric return indexes.size(); 674*0b57cec5SDimitry Andric } 675*0b57cec5SDimitry Andric 676*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 677*0b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 678*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 679*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 680*0b57cec5SDimitry Andric 681*0b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 682*0b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 683*0b57cec5SDimitry Andric 684*0b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 685*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 686*0b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 687*0b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 688*0b57cec5SDimitry Andric if (name) { 689*0b57cec5SDimitry Andric if (regexp.Execute(name)) 690*0b57cec5SDimitry Andric indexes.push_back(i); 691*0b57cec5SDimitry Andric } 692*0b57cec5SDimitry Andric } 693*0b57cec5SDimitry Andric } 694*0b57cec5SDimitry Andric return indexes.size() - prev_size; 695*0b57cec5SDimitry Andric } 696*0b57cec5SDimitry Andric 697*0b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 698*0b57cec5SDimitry Andric const RegularExpression ®exp, SymbolType symbol_type, 699*0b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 700*0b57cec5SDimitry Andric std::vector<uint32_t> &indexes) { 701*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 702*0b57cec5SDimitry Andric 703*0b57cec5SDimitry Andric uint32_t prev_size = indexes.size(); 704*0b57cec5SDimitry Andric uint32_t sym_end = m_symbols.size(); 705*0b57cec5SDimitry Andric 706*0b57cec5SDimitry Andric for (uint32_t i = 0; i < sym_end; i++) { 707*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 708*0b57cec5SDimitry Andric m_symbols[i].GetType() == symbol_type) { 709*0b57cec5SDimitry Andric if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 710*0b57cec5SDimitry Andric continue; 711*0b57cec5SDimitry Andric 712*0b57cec5SDimitry Andric const char *name = m_symbols[i].GetName().AsCString(); 713*0b57cec5SDimitry Andric if (name) { 714*0b57cec5SDimitry Andric if (regexp.Execute(name)) 715*0b57cec5SDimitry Andric indexes.push_back(i); 716*0b57cec5SDimitry Andric } 717*0b57cec5SDimitry Andric } 718*0b57cec5SDimitry Andric } 719*0b57cec5SDimitry Andric return indexes.size() - prev_size; 720*0b57cec5SDimitry Andric } 721*0b57cec5SDimitry Andric 722*0b57cec5SDimitry Andric Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, 723*0b57cec5SDimitry Andric Debug symbol_debug_type, 724*0b57cec5SDimitry Andric Visibility symbol_visibility, 725*0b57cec5SDimitry Andric uint32_t &start_idx) { 726*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 727*0b57cec5SDimitry Andric 728*0b57cec5SDimitry Andric const size_t count = m_symbols.size(); 729*0b57cec5SDimitry Andric for (size_t idx = start_idx; idx < count; ++idx) { 730*0b57cec5SDimitry Andric if (symbol_type == eSymbolTypeAny || 731*0b57cec5SDimitry Andric m_symbols[idx].GetType() == symbol_type) { 732*0b57cec5SDimitry Andric if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { 733*0b57cec5SDimitry Andric start_idx = idx; 734*0b57cec5SDimitry Andric return &m_symbols[idx]; 735*0b57cec5SDimitry Andric } 736*0b57cec5SDimitry Andric } 737*0b57cec5SDimitry Andric } 738*0b57cec5SDimitry Andric return nullptr; 739*0b57cec5SDimitry Andric } 740*0b57cec5SDimitry Andric 741*0b57cec5SDimitry Andric size_t 742*0b57cec5SDimitry Andric Symtab::FindAllSymbolsWithNameAndType(ConstString name, 743*0b57cec5SDimitry Andric SymbolType symbol_type, 744*0b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 745*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 746*0b57cec5SDimitry Andric 747*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 748*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 749*0b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 750*0b57cec5SDimitry Andric // uniqued string NAME_STR below. 751*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 752*0b57cec5SDimitry Andric InitNameIndexes(); 753*0b57cec5SDimitry Andric 754*0b57cec5SDimitry Andric if (name) { 755*0b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 756*0b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 757*0b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 758*0b57cec5SDimitry Andric } 759*0b57cec5SDimitry Andric return symbol_indexes.size(); 760*0b57cec5SDimitry Andric } 761*0b57cec5SDimitry Andric 762*0b57cec5SDimitry Andric size_t Symtab::FindAllSymbolsWithNameAndType( 763*0b57cec5SDimitry Andric ConstString name, SymbolType symbol_type, Debug symbol_debug_type, 764*0b57cec5SDimitry Andric Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { 765*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 766*0b57cec5SDimitry Andric 767*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 768*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 769*0b57cec5SDimitry Andric // Initialize all of the lookup by name indexes before converting NAME to a 770*0b57cec5SDimitry Andric // uniqued string NAME_STR below. 771*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 772*0b57cec5SDimitry Andric InitNameIndexes(); 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric if (name) { 775*0b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 776*0b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 777*0b57cec5SDimitry Andric AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 778*0b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 779*0b57cec5SDimitry Andric } 780*0b57cec5SDimitry Andric return symbol_indexes.size(); 781*0b57cec5SDimitry Andric } 782*0b57cec5SDimitry Andric 783*0b57cec5SDimitry Andric size_t Symtab::FindAllSymbolsMatchingRexExAndType( 784*0b57cec5SDimitry Andric const RegularExpression ®ex, SymbolType symbol_type, 785*0b57cec5SDimitry Andric Debug symbol_debug_type, Visibility symbol_visibility, 786*0b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes) { 787*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 788*0b57cec5SDimitry Andric 789*0b57cec5SDimitry Andric AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, 790*0b57cec5SDimitry Andric symbol_visibility, symbol_indexes); 791*0b57cec5SDimitry Andric return symbol_indexes.size(); 792*0b57cec5SDimitry Andric } 793*0b57cec5SDimitry Andric 794*0b57cec5SDimitry Andric Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, 795*0b57cec5SDimitry Andric SymbolType symbol_type, 796*0b57cec5SDimitry Andric Debug symbol_debug_type, 797*0b57cec5SDimitry Andric Visibility symbol_visibility) { 798*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 799*0b57cec5SDimitry Andric 800*0b57cec5SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 801*0b57cec5SDimitry Andric Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 802*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 803*0b57cec5SDimitry Andric InitNameIndexes(); 804*0b57cec5SDimitry Andric 805*0b57cec5SDimitry Andric if (name) { 806*0b57cec5SDimitry Andric std::vector<uint32_t> matching_indexes; 807*0b57cec5SDimitry Andric // The string table did have a string that matched, but we need to check 808*0b57cec5SDimitry Andric // the symbols and match the symbol_type if any was given. 809*0b57cec5SDimitry Andric if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 810*0b57cec5SDimitry Andric symbol_visibility, 811*0b57cec5SDimitry Andric matching_indexes)) { 812*0b57cec5SDimitry Andric std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 813*0b57cec5SDimitry Andric for (pos = matching_indexes.begin(); pos != end; ++pos) { 814*0b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(*pos); 815*0b57cec5SDimitry Andric 816*0b57cec5SDimitry Andric if (symbol->Compare(name, symbol_type)) 817*0b57cec5SDimitry Andric return symbol; 818*0b57cec5SDimitry Andric } 819*0b57cec5SDimitry Andric } 820*0b57cec5SDimitry Andric } 821*0b57cec5SDimitry Andric return nullptr; 822*0b57cec5SDimitry Andric } 823*0b57cec5SDimitry Andric 824*0b57cec5SDimitry Andric typedef struct { 825*0b57cec5SDimitry Andric const Symtab *symtab; 826*0b57cec5SDimitry Andric const addr_t file_addr; 827*0b57cec5SDimitry Andric Symbol *match_symbol; 828*0b57cec5SDimitry Andric const uint32_t *match_index_ptr; 829*0b57cec5SDimitry Andric addr_t match_offset; 830*0b57cec5SDimitry Andric } SymbolSearchInfo; 831*0b57cec5SDimitry Andric 832*0b57cec5SDimitry Andric // Add all the section file start address & size to the RangeVector, recusively 833*0b57cec5SDimitry Andric // adding any children sections. 834*0b57cec5SDimitry Andric static void AddSectionsToRangeMap(SectionList *sectlist, 835*0b57cec5SDimitry Andric RangeVector<addr_t, addr_t> §ion_ranges) { 836*0b57cec5SDimitry Andric const int num_sections = sectlist->GetNumSections(0); 837*0b57cec5SDimitry Andric for (int i = 0; i < num_sections; i++) { 838*0b57cec5SDimitry Andric SectionSP sect_sp = sectlist->GetSectionAtIndex(i); 839*0b57cec5SDimitry Andric if (sect_sp) { 840*0b57cec5SDimitry Andric SectionList &child_sectlist = sect_sp->GetChildren(); 841*0b57cec5SDimitry Andric 842*0b57cec5SDimitry Andric // If this section has children, add the children to the RangeVector. 843*0b57cec5SDimitry Andric // Else add this section to the RangeVector. 844*0b57cec5SDimitry Andric if (child_sectlist.GetNumSections(0) > 0) { 845*0b57cec5SDimitry Andric AddSectionsToRangeMap(&child_sectlist, section_ranges); 846*0b57cec5SDimitry Andric } else { 847*0b57cec5SDimitry Andric size_t size = sect_sp->GetByteSize(); 848*0b57cec5SDimitry Andric if (size > 0) { 849*0b57cec5SDimitry Andric addr_t base_addr = sect_sp->GetFileAddress(); 850*0b57cec5SDimitry Andric RangeVector<addr_t, addr_t>::Entry entry; 851*0b57cec5SDimitry Andric entry.SetRangeBase(base_addr); 852*0b57cec5SDimitry Andric entry.SetByteSize(size); 853*0b57cec5SDimitry Andric section_ranges.Append(entry); 854*0b57cec5SDimitry Andric } 855*0b57cec5SDimitry Andric } 856*0b57cec5SDimitry Andric } 857*0b57cec5SDimitry Andric } 858*0b57cec5SDimitry Andric } 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric void Symtab::InitAddressIndexes() { 861*0b57cec5SDimitry Andric // Protected function, no need to lock mutex... 862*0b57cec5SDimitry Andric if (!m_file_addr_to_index_computed && !m_symbols.empty()) { 863*0b57cec5SDimitry Andric m_file_addr_to_index_computed = true; 864*0b57cec5SDimitry Andric 865*0b57cec5SDimitry Andric FileRangeToIndexMap::Entry entry; 866*0b57cec5SDimitry Andric const_iterator begin = m_symbols.begin(); 867*0b57cec5SDimitry Andric const_iterator end = m_symbols.end(); 868*0b57cec5SDimitry Andric for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 869*0b57cec5SDimitry Andric if (pos->ValueIsAddress()) { 870*0b57cec5SDimitry Andric entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); 871*0b57cec5SDimitry Andric entry.SetByteSize(pos->GetByteSize()); 872*0b57cec5SDimitry Andric entry.data = std::distance(begin, pos); 873*0b57cec5SDimitry Andric m_file_addr_to_index.Append(entry); 874*0b57cec5SDimitry Andric } 875*0b57cec5SDimitry Andric } 876*0b57cec5SDimitry Andric const size_t num_entries = m_file_addr_to_index.GetSize(); 877*0b57cec5SDimitry Andric if (num_entries > 0) { 878*0b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 879*0b57cec5SDimitry Andric 880*0b57cec5SDimitry Andric // Create a RangeVector with the start & size of all the sections for 881*0b57cec5SDimitry Andric // this objfile. We'll need to check this for any FileRangeToIndexMap 882*0b57cec5SDimitry Andric // entries with an uninitialized size, which could potentially be a large 883*0b57cec5SDimitry Andric // number so reconstituting the weak pointer is busywork when it is 884*0b57cec5SDimitry Andric // invariant information. 885*0b57cec5SDimitry Andric SectionList *sectlist = m_objfile->GetSectionList(); 886*0b57cec5SDimitry Andric RangeVector<addr_t, addr_t> section_ranges; 887*0b57cec5SDimitry Andric if (sectlist) { 888*0b57cec5SDimitry Andric AddSectionsToRangeMap(sectlist, section_ranges); 889*0b57cec5SDimitry Andric section_ranges.Sort(); 890*0b57cec5SDimitry Andric } 891*0b57cec5SDimitry Andric 892*0b57cec5SDimitry Andric // Iterate through the FileRangeToIndexMap and fill in the size for any 893*0b57cec5SDimitry Andric // entries that didn't already have a size from the Symbol (e.g. if we 894*0b57cec5SDimitry Andric // have a plain linker symbol with an address only, instead of debug info 895*0b57cec5SDimitry Andric // where we get an address and a size and a type, etc.) 896*0b57cec5SDimitry Andric for (size_t i = 0; i < num_entries; i++) { 897*0b57cec5SDimitry Andric FileRangeToIndexMap::Entry *entry = 898*0b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(i); 899*0b57cec5SDimitry Andric if (entry->GetByteSize() > 0) 900*0b57cec5SDimitry Andric continue; 901*0b57cec5SDimitry Andric addr_t curr_base_addr = entry->GetRangeBase(); 902*0b57cec5SDimitry Andric // Symbols with non-zero size will show after zero-sized symbols on the 903*0b57cec5SDimitry Andric // same address. So do not set size of a non-last zero-sized symbol. 904*0b57cec5SDimitry Andric if (i == num_entries - 1 || 905*0b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(i + 1) 906*0b57cec5SDimitry Andric ->GetRangeBase() != curr_base_addr) { 907*0b57cec5SDimitry Andric const RangeVector<addr_t, addr_t>::Entry *containing_section = 908*0b57cec5SDimitry Andric section_ranges.FindEntryThatContains(curr_base_addr); 909*0b57cec5SDimitry Andric 910*0b57cec5SDimitry Andric // Use the end of the section as the default max size of the symbol 911*0b57cec5SDimitry Andric addr_t sym_size = 0; 912*0b57cec5SDimitry Andric if (containing_section) { 913*0b57cec5SDimitry Andric sym_size = 914*0b57cec5SDimitry Andric containing_section->GetByteSize() - 915*0b57cec5SDimitry Andric (entry->GetRangeBase() - containing_section->GetRangeBase()); 916*0b57cec5SDimitry Andric } 917*0b57cec5SDimitry Andric 918*0b57cec5SDimitry Andric for (size_t j = i; j < num_entries; j++) { 919*0b57cec5SDimitry Andric FileRangeToIndexMap::Entry *next_entry = 920*0b57cec5SDimitry Andric m_file_addr_to_index.GetMutableEntryAtIndex(j); 921*0b57cec5SDimitry Andric addr_t next_base_addr = next_entry->GetRangeBase(); 922*0b57cec5SDimitry Andric if (next_base_addr > curr_base_addr) { 923*0b57cec5SDimitry Andric addr_t size_to_next_symbol = next_base_addr - curr_base_addr; 924*0b57cec5SDimitry Andric 925*0b57cec5SDimitry Andric // Take the difference between this symbol and the next one as 926*0b57cec5SDimitry Andric // its size, if it is less than the size of the section. 927*0b57cec5SDimitry Andric if (sym_size == 0 || size_to_next_symbol < sym_size) { 928*0b57cec5SDimitry Andric sym_size = size_to_next_symbol; 929*0b57cec5SDimitry Andric } 930*0b57cec5SDimitry Andric break; 931*0b57cec5SDimitry Andric } 932*0b57cec5SDimitry Andric } 933*0b57cec5SDimitry Andric 934*0b57cec5SDimitry Andric if (sym_size > 0) { 935*0b57cec5SDimitry Andric entry->SetByteSize(sym_size); 936*0b57cec5SDimitry Andric Symbol &symbol = m_symbols[entry->data]; 937*0b57cec5SDimitry Andric symbol.SetByteSize(sym_size); 938*0b57cec5SDimitry Andric symbol.SetSizeIsSynthesized(true); 939*0b57cec5SDimitry Andric } 940*0b57cec5SDimitry Andric } 941*0b57cec5SDimitry Andric } 942*0b57cec5SDimitry Andric 943*0b57cec5SDimitry Andric // Sort again in case the range size changes the ordering 944*0b57cec5SDimitry Andric m_file_addr_to_index.Sort(); 945*0b57cec5SDimitry Andric } 946*0b57cec5SDimitry Andric } 947*0b57cec5SDimitry Andric } 948*0b57cec5SDimitry Andric 949*0b57cec5SDimitry Andric void Symtab::CalculateSymbolSizes() { 950*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 951*0b57cec5SDimitry Andric // Size computation happens inside InitAddressIndexes. 952*0b57cec5SDimitry Andric InitAddressIndexes(); 953*0b57cec5SDimitry Andric } 954*0b57cec5SDimitry Andric 955*0b57cec5SDimitry Andric Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { 956*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 957*0b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 958*0b57cec5SDimitry Andric InitAddressIndexes(); 959*0b57cec5SDimitry Andric 960*0b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 961*0b57cec5SDimitry Andric m_file_addr_to_index.FindEntryStartsAt(file_addr); 962*0b57cec5SDimitry Andric if (entry) { 963*0b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 964*0b57cec5SDimitry Andric if (symbol->GetFileAddress() == file_addr) 965*0b57cec5SDimitry Andric return symbol; 966*0b57cec5SDimitry Andric } 967*0b57cec5SDimitry Andric return nullptr; 968*0b57cec5SDimitry Andric } 969*0b57cec5SDimitry Andric 970*0b57cec5SDimitry Andric Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { 971*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 972*0b57cec5SDimitry Andric 973*0b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 974*0b57cec5SDimitry Andric InitAddressIndexes(); 975*0b57cec5SDimitry Andric 976*0b57cec5SDimitry Andric const FileRangeToIndexMap::Entry *entry = 977*0b57cec5SDimitry Andric m_file_addr_to_index.FindEntryThatContains(file_addr); 978*0b57cec5SDimitry Andric if (entry) { 979*0b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(entry->data); 980*0b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) 981*0b57cec5SDimitry Andric return symbol; 982*0b57cec5SDimitry Andric } 983*0b57cec5SDimitry Andric return nullptr; 984*0b57cec5SDimitry Andric } 985*0b57cec5SDimitry Andric 986*0b57cec5SDimitry Andric void Symtab::ForEachSymbolContainingFileAddress( 987*0b57cec5SDimitry Andric addr_t file_addr, std::function<bool(Symbol *)> const &callback) { 988*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 989*0b57cec5SDimitry Andric 990*0b57cec5SDimitry Andric if (!m_file_addr_to_index_computed) 991*0b57cec5SDimitry Andric InitAddressIndexes(); 992*0b57cec5SDimitry Andric 993*0b57cec5SDimitry Andric std::vector<uint32_t> all_addr_indexes; 994*0b57cec5SDimitry Andric 995*0b57cec5SDimitry Andric // Get all symbols with file_addr 996*0b57cec5SDimitry Andric const size_t addr_match_count = 997*0b57cec5SDimitry Andric m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, 998*0b57cec5SDimitry Andric all_addr_indexes); 999*0b57cec5SDimitry Andric 1000*0b57cec5SDimitry Andric for (size_t i = 0; i < addr_match_count; ++i) { 1001*0b57cec5SDimitry Andric Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); 1002*0b57cec5SDimitry Andric if (symbol->ContainsFileAddress(file_addr)) { 1003*0b57cec5SDimitry Andric if (!callback(symbol)) 1004*0b57cec5SDimitry Andric break; 1005*0b57cec5SDimitry Andric } 1006*0b57cec5SDimitry Andric } 1007*0b57cec5SDimitry Andric } 1008*0b57cec5SDimitry Andric 1009*0b57cec5SDimitry Andric void Symtab::SymbolIndicesToSymbolContextList( 1010*0b57cec5SDimitry Andric std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { 1011*0b57cec5SDimitry Andric // No need to protect this call using m_mutex all other method calls are 1012*0b57cec5SDimitry Andric // already thread safe. 1013*0b57cec5SDimitry Andric 1014*0b57cec5SDimitry Andric const bool merge_symbol_into_function = true; 1015*0b57cec5SDimitry Andric size_t num_indices = symbol_indexes.size(); 1016*0b57cec5SDimitry Andric if (num_indices > 0) { 1017*0b57cec5SDimitry Andric SymbolContext sc; 1018*0b57cec5SDimitry Andric sc.module_sp = m_objfile->GetModule(); 1019*0b57cec5SDimitry Andric for (size_t i = 0; i < num_indices; i++) { 1020*0b57cec5SDimitry Andric sc.symbol = SymbolAtIndex(symbol_indexes[i]); 1021*0b57cec5SDimitry Andric if (sc.symbol) 1022*0b57cec5SDimitry Andric sc_list.AppendIfUnique(sc, merge_symbol_into_function); 1023*0b57cec5SDimitry Andric } 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric } 1026*0b57cec5SDimitry Andric 1027*0b57cec5SDimitry Andric size_t Symtab::FindFunctionSymbols(ConstString name, 1028*0b57cec5SDimitry Andric uint32_t name_type_mask, 1029*0b57cec5SDimitry Andric SymbolContextList &sc_list) { 1030*0b57cec5SDimitry Andric size_t count = 0; 1031*0b57cec5SDimitry Andric std::vector<uint32_t> symbol_indexes; 1032*0b57cec5SDimitry Andric 1033*0b57cec5SDimitry Andric // eFunctionNameTypeAuto should be pre-resolved by a call to 1034*0b57cec5SDimitry Andric // Module::LookupInfo::LookupInfo() 1035*0b57cec5SDimitry Andric assert((name_type_mask & eFunctionNameTypeAuto) == 0); 1036*0b57cec5SDimitry Andric 1037*0b57cec5SDimitry Andric if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { 1038*0b57cec5SDimitry Andric std::vector<uint32_t> temp_symbol_indexes; 1039*0b57cec5SDimitry Andric FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); 1040*0b57cec5SDimitry Andric 1041*0b57cec5SDimitry Andric unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 1042*0b57cec5SDimitry Andric if (temp_symbol_indexes_size > 0) { 1043*0b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1044*0b57cec5SDimitry Andric for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { 1045*0b57cec5SDimitry Andric SymbolContext sym_ctx; 1046*0b57cec5SDimitry Andric sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); 1047*0b57cec5SDimitry Andric if (sym_ctx.symbol) { 1048*0b57cec5SDimitry Andric switch (sym_ctx.symbol->GetType()) { 1049*0b57cec5SDimitry Andric case eSymbolTypeCode: 1050*0b57cec5SDimitry Andric case eSymbolTypeResolver: 1051*0b57cec5SDimitry Andric case eSymbolTypeReExported: 1052*0b57cec5SDimitry Andric symbol_indexes.push_back(temp_symbol_indexes[i]); 1053*0b57cec5SDimitry Andric break; 1054*0b57cec5SDimitry Andric default: 1055*0b57cec5SDimitry Andric break; 1056*0b57cec5SDimitry Andric } 1057*0b57cec5SDimitry Andric } 1058*0b57cec5SDimitry Andric } 1059*0b57cec5SDimitry Andric } 1060*0b57cec5SDimitry Andric } 1061*0b57cec5SDimitry Andric 1062*0b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeBase) { 1063*0b57cec5SDimitry Andric // From mangled names we can't tell what is a basename and what is a method 1064*0b57cec5SDimitry Andric // name, so we just treat them the same 1065*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 1066*0b57cec5SDimitry Andric InitNameIndexes(); 1067*0b57cec5SDimitry Andric 1068*0b57cec5SDimitry Andric if (!m_basename_to_index.IsEmpty()) { 1069*0b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 1070*0b57cec5SDimitry Andric for (match = m_basename_to_index.FindFirstValueForName(name); 1071*0b57cec5SDimitry Andric match != nullptr; 1072*0b57cec5SDimitry Andric match = m_basename_to_index.FindNextValueForName(match)) { 1073*0b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 1074*0b57cec5SDimitry Andric } 1075*0b57cec5SDimitry Andric } 1076*0b57cec5SDimitry Andric } 1077*0b57cec5SDimitry Andric 1078*0b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeMethod) { 1079*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 1080*0b57cec5SDimitry Andric InitNameIndexes(); 1081*0b57cec5SDimitry Andric 1082*0b57cec5SDimitry Andric if (!m_method_to_index.IsEmpty()) { 1083*0b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 1084*0b57cec5SDimitry Andric for (match = m_method_to_index.FindFirstValueForName(name); 1085*0b57cec5SDimitry Andric match != nullptr; 1086*0b57cec5SDimitry Andric match = m_method_to_index.FindNextValueForName(match)) { 1087*0b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 1088*0b57cec5SDimitry Andric } 1089*0b57cec5SDimitry Andric } 1090*0b57cec5SDimitry Andric } 1091*0b57cec5SDimitry Andric 1092*0b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeSelector) { 1093*0b57cec5SDimitry Andric if (!m_name_indexes_computed) 1094*0b57cec5SDimitry Andric InitNameIndexes(); 1095*0b57cec5SDimitry Andric 1096*0b57cec5SDimitry Andric if (!m_selector_to_index.IsEmpty()) { 1097*0b57cec5SDimitry Andric const UniqueCStringMap<uint32_t>::Entry *match; 1098*0b57cec5SDimitry Andric for (match = m_selector_to_index.FindFirstValueForName(name); 1099*0b57cec5SDimitry Andric match != nullptr; 1100*0b57cec5SDimitry Andric match = m_selector_to_index.FindNextValueForName(match)) { 1101*0b57cec5SDimitry Andric symbol_indexes.push_back(match->value); 1102*0b57cec5SDimitry Andric } 1103*0b57cec5SDimitry Andric } 1104*0b57cec5SDimitry Andric } 1105*0b57cec5SDimitry Andric 1106*0b57cec5SDimitry Andric if (!symbol_indexes.empty()) { 1107*0b57cec5SDimitry Andric llvm::sort(symbol_indexes.begin(), symbol_indexes.end()); 1108*0b57cec5SDimitry Andric symbol_indexes.erase( 1109*0b57cec5SDimitry Andric std::unique(symbol_indexes.begin(), symbol_indexes.end()), 1110*0b57cec5SDimitry Andric symbol_indexes.end()); 1111*0b57cec5SDimitry Andric count = symbol_indexes.size(); 1112*0b57cec5SDimitry Andric SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); 1113*0b57cec5SDimitry Andric } 1114*0b57cec5SDimitry Andric 1115*0b57cec5SDimitry Andric return count; 1116*0b57cec5SDimitry Andric } 1117*0b57cec5SDimitry Andric 1118*0b57cec5SDimitry Andric const Symbol *Symtab::GetParent(Symbol *child_symbol) const { 1119*0b57cec5SDimitry Andric uint32_t child_idx = GetIndexForSymbol(child_symbol); 1120*0b57cec5SDimitry Andric if (child_idx != UINT32_MAX && child_idx > 0) { 1121*0b57cec5SDimitry Andric for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { 1122*0b57cec5SDimitry Andric const Symbol *symbol = SymbolAtIndex(idx); 1123*0b57cec5SDimitry Andric const uint32_t sibling_idx = symbol->GetSiblingIndex(); 1124*0b57cec5SDimitry Andric if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) 1125*0b57cec5SDimitry Andric return symbol; 1126*0b57cec5SDimitry Andric } 1127*0b57cec5SDimitry Andric } 1128*0b57cec5SDimitry Andric return nullptr; 1129*0b57cec5SDimitry Andric } 1130