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