1 //===-- Symtab.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <map> 11 #include <set> 12 13 #include "Plugins/Language/ObjC/ObjCLanguage.h" 14 15 #include "lldb/Core/Module.h" 16 #include "lldb/Core/RichManglingContext.h" 17 #include "lldb/Core/STLUtils.h" 18 #include "lldb/Core/Section.h" 19 #include "lldb/Symbol/ObjectFile.h" 20 #include "lldb/Symbol/Symbol.h" 21 #include "lldb/Symbol/SymbolContext.h" 22 #include "lldb/Symbol/Symtab.h" 23 #include "lldb/Utility/RegularExpression.h" 24 #include "lldb/Utility/Stream.h" 25 #include "lldb/Utility/Timer.h" 26 27 #include "llvm/ADT/StringRef.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 Symtab::Symtab(ObjectFile *objfile) 33 : m_objfile(objfile), m_symbols(), m_file_addr_to_index(), 34 m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false), 35 m_name_indexes_computed(false) {} 36 37 Symtab::~Symtab() {} 38 39 void Symtab::Reserve(size_t count) { 40 // Clients should grab the mutex from this symbol table and lock it manually 41 // when calling this function to avoid performance issues. 42 m_symbols.reserve(count); 43 } 44 45 Symbol *Symtab::Resize(size_t count) { 46 // Clients should grab the mutex from this symbol table and lock it manually 47 // when calling this function to avoid performance issues. 48 m_symbols.resize(count); 49 return m_symbols.empty() ? nullptr : &m_symbols[0]; 50 } 51 52 uint32_t Symtab::AddSymbol(const Symbol &symbol) { 53 // Clients should grab the mutex from this symbol table and lock it manually 54 // when calling this function to avoid performance issues. 55 uint32_t symbol_idx = m_symbols.size(); 56 m_name_to_index.Clear(); 57 m_file_addr_to_index.Clear(); 58 m_symbols.push_back(symbol); 59 m_file_addr_to_index_computed = false; 60 m_name_indexes_computed = false; 61 return symbol_idx; 62 } 63 64 size_t Symtab::GetNumSymbols() const { 65 std::lock_guard<std::recursive_mutex> guard(m_mutex); 66 return m_symbols.size(); 67 } 68 69 void Symtab::SectionFileAddressesChanged() { 70 m_name_to_index.Clear(); 71 m_file_addr_to_index_computed = false; 72 } 73 74 void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) { 75 std::lock_guard<std::recursive_mutex> guard(m_mutex); 76 77 // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 78 s->Indent(); 79 const FileSpec &file_spec = m_objfile->GetFileSpec(); 80 const char *object_name = nullptr; 81 if (m_objfile->GetModule()) 82 object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 83 84 if (file_spec) 85 s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, 86 file_spec.GetPath().c_str(), object_name ? "(" : "", 87 object_name ? object_name : "", object_name ? ")" : "", 88 (uint64_t)m_symbols.size()); 89 else 90 s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); 91 92 if (!m_symbols.empty()) { 93 switch (sort_order) { 94 case eSortOrderNone: { 95 s->PutCString(":\n"); 96 DumpSymbolHeader(s); 97 const_iterator begin = m_symbols.begin(); 98 const_iterator end = m_symbols.end(); 99 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 100 s->Indent(); 101 pos->Dump(s, target, std::distance(begin, pos)); 102 } 103 } break; 104 105 case eSortOrderByName: { 106 // Although we maintain a lookup by exact name map, the table isn't 107 // sorted by name. So we must make the ordered symbol list up ourselves. 108 s->PutCString(" (sorted by name):\n"); 109 DumpSymbolHeader(s); 110 typedef std::multimap<const char *, const Symbol *, 111 CStringCompareFunctionObject> 112 CStringToSymbol; 113 CStringToSymbol name_map; 114 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 115 pos != end; ++pos) { 116 const char *name = pos->GetName().AsCString(); 117 if (name && name[0]) 118 name_map.insert(std::make_pair(name, &(*pos))); 119 } 120 121 for (CStringToSymbol::const_iterator pos = name_map.begin(), 122 end = name_map.end(); 123 pos != end; ++pos) { 124 s->Indent(); 125 pos->second->Dump(s, target, pos->second - &m_symbols[0]); 126 } 127 } break; 128 129 case eSortOrderByAddress: 130 s->PutCString(" (sorted by address):\n"); 131 DumpSymbolHeader(s); 132 if (!m_file_addr_to_index_computed) 133 InitAddressIndexes(); 134 const size_t num_entries = m_file_addr_to_index.GetSize(); 135 for (size_t i = 0; i < num_entries; ++i) { 136 s->Indent(); 137 const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; 138 m_symbols[symbol_idx].Dump(s, target, symbol_idx); 139 } 140 break; 141 } 142 } 143 } 144 145 void Symtab::Dump(Stream *s, Target *target, 146 std::vector<uint32_t> &indexes) const { 147 std::lock_guard<std::recursive_mutex> guard(m_mutex); 148 149 const size_t num_symbols = GetNumSymbols(); 150 // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 151 s->Indent(); 152 s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", 153 (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); 154 s->IndentMore(); 155 156 if (!indexes.empty()) { 157 std::vector<uint32_t>::const_iterator pos; 158 std::vector<uint32_t>::const_iterator end = indexes.end(); 159 DumpSymbolHeader(s); 160 for (pos = indexes.begin(); pos != end; ++pos) { 161 size_t idx = *pos; 162 if (idx < num_symbols) { 163 s->Indent(); 164 m_symbols[idx].Dump(s, target, idx); 165 } 166 } 167 } 168 s->IndentLess(); 169 } 170 171 void Symtab::DumpSymbolHeader(Stream *s) { 172 s->Indent(" Debug symbol\n"); 173 s->Indent(" |Synthetic symbol\n"); 174 s->Indent(" ||Externally Visible\n"); 175 s->Indent(" |||\n"); 176 s->Indent("Index UserID DSX Type File Address/Value Load " 177 "Address Size Flags Name\n"); 178 s->Indent("------- ------ --- --------------- ------------------ " 179 "------------------ ------------------ ---------- " 180 "----------------------------------\n"); 181 } 182 183 static int CompareSymbolID(const void *key, const void *p) { 184 const user_id_t match_uid = *(const user_id_t *)key; 185 const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); 186 if (match_uid < symbol_uid) 187 return -1; 188 if (match_uid > symbol_uid) 189 return 1; 190 return 0; 191 } 192 193 Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const { 194 std::lock_guard<std::recursive_mutex> guard(m_mutex); 195 196 Symbol *symbol = 197 (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(), 198 sizeof(m_symbols[0]), CompareSymbolID); 199 return symbol; 200 } 201 202 Symbol *Symtab::SymbolAtIndex(size_t idx) { 203 // Clients should grab the mutex from this symbol table and lock it manually 204 // when calling this function to avoid performance issues. 205 if (idx < m_symbols.size()) 206 return &m_symbols[idx]; 207 return nullptr; 208 } 209 210 const Symbol *Symtab::SymbolAtIndex(size_t idx) const { 211 // Clients should grab the mutex from this symbol table and lock it manually 212 // when calling this function to avoid performance issues. 213 if (idx < m_symbols.size()) 214 return &m_symbols[idx]; 215 return nullptr; 216 } 217 218 //---------------------------------------------------------------------- 219 // InitNameIndexes 220 //---------------------------------------------------------------------- 221 static bool lldb_skip_name(llvm::StringRef mangled, 222 Mangled::ManglingScheme scheme) { 223 switch (scheme) { 224 case Mangled::eManglingSchemeItanium: { 225 if (mangled.size() < 3 || !mangled.startswith("_Z")) 226 return true; 227 228 // Avoid the following types of symbols in the index. 229 switch (mangled[2]) { 230 case 'G': // guard variables 231 case 'T': // virtual tables, VTT structures, typeinfo structures + names 232 case 'Z': // named local entities (if we eventually handle 233 // eSymbolTypeData, we will want this back) 234 return true; 235 236 default: 237 break; 238 } 239 240 // Include this name in the index. 241 return false; 242 } 243 244 // No filters for this scheme yet. Include all names in indexing. 245 case Mangled::eManglingSchemeMSVC: 246 return false; 247 248 // Don't try and demangle things we can't categorize. 249 case Mangled::eManglingSchemeNone: 250 return true; 251 } 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 std::sort here is strictly for 611 // performance, 612 // not correctness. The indexes vector tends to be "close" to sorted, which 613 // the stable sort handles better. 614 615 std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 616 617 SymbolIndexComparator comparator(m_symbols, addr_cache); 618 std::stable_sort(indexes.begin(), indexes.end(), comparator); 619 620 // Remove any duplicates if requested 621 if (remove_duplicates) { 622 auto last = std::unique(indexes.begin(), indexes.end()); 623 indexes.erase(last, indexes.end()); 624 } 625 } 626 627 uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, 628 std::vector<uint32_t> &indexes) { 629 std::lock_guard<std::recursive_mutex> guard(m_mutex); 630 631 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 632 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 633 if (symbol_name) { 634 if (!m_name_indexes_computed) 635 InitNameIndexes(); 636 637 return m_name_to_index.GetValues(symbol_name, indexes); 638 } 639 return 0; 640 } 641 642 uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, 643 Debug symbol_debug_type, 644 Visibility symbol_visibility, 645 std::vector<uint32_t> &indexes) { 646 std::lock_guard<std::recursive_mutex> guard(m_mutex); 647 648 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 649 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 650 if (symbol_name) { 651 const size_t old_size = indexes.size(); 652 if (!m_name_indexes_computed) 653 InitNameIndexes(); 654 655 std::vector<uint32_t> all_name_indexes; 656 const size_t name_match_count = 657 m_name_to_index.GetValues(symbol_name, all_name_indexes); 658 for (size_t i = 0; i < name_match_count; ++i) { 659 if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, 660 symbol_visibility)) 661 indexes.push_back(all_name_indexes[i]); 662 } 663 return indexes.size() - old_size; 664 } 665 return 0; 666 } 667 668 uint32_t 669 Symtab::AppendSymbolIndexesWithNameAndType(const ConstString &symbol_name, 670 SymbolType symbol_type, 671 std::vector<uint32_t> &indexes) { 672 std::lock_guard<std::recursive_mutex> guard(m_mutex); 673 674 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { 675 std::vector<uint32_t>::iterator pos = indexes.begin(); 676 while (pos != indexes.end()) { 677 if (symbol_type == eSymbolTypeAny || 678 m_symbols[*pos].GetType() == symbol_type) 679 ++pos; 680 else 681 pos = indexes.erase(pos); 682 } 683 } 684 return indexes.size(); 685 } 686 687 uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 688 const ConstString &symbol_name, SymbolType symbol_type, 689 Debug symbol_debug_type, Visibility symbol_visibility, 690 std::vector<uint32_t> &indexes) { 691 std::lock_guard<std::recursive_mutex> guard(m_mutex); 692 693 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, 694 symbol_visibility, indexes) > 0) { 695 std::vector<uint32_t>::iterator pos = indexes.begin(); 696 while (pos != indexes.end()) { 697 if (symbol_type == eSymbolTypeAny || 698 m_symbols[*pos].GetType() == symbol_type) 699 ++pos; 700 else 701 pos = indexes.erase(pos); 702 } 703 } 704 return indexes.size(); 705 } 706 707 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 708 const RegularExpression ®exp, SymbolType symbol_type, 709 std::vector<uint32_t> &indexes) { 710 std::lock_guard<std::recursive_mutex> guard(m_mutex); 711 712 uint32_t prev_size = indexes.size(); 713 uint32_t sym_end = m_symbols.size(); 714 715 for (uint32_t i = 0; i < sym_end; i++) { 716 if (symbol_type == eSymbolTypeAny || 717 m_symbols[i].GetType() == symbol_type) { 718 const char *name = m_symbols[i].GetName().AsCString(); 719 if (name) { 720 if (regexp.Execute(name)) 721 indexes.push_back(i); 722 } 723 } 724 } 725 return indexes.size() - prev_size; 726 } 727 728 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 729 const RegularExpression ®exp, SymbolType symbol_type, 730 Debug symbol_debug_type, Visibility symbol_visibility, 731 std::vector<uint32_t> &indexes) { 732 std::lock_guard<std::recursive_mutex> guard(m_mutex); 733 734 uint32_t prev_size = indexes.size(); 735 uint32_t sym_end = m_symbols.size(); 736 737 for (uint32_t i = 0; i < sym_end; i++) { 738 if (symbol_type == eSymbolTypeAny || 739 m_symbols[i].GetType() == symbol_type) { 740 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) 741 continue; 742 743 const char *name = m_symbols[i].GetName().AsCString(); 744 if (name) { 745 if (regexp.Execute(name)) 746 indexes.push_back(i); 747 } 748 } 749 } 750 return indexes.size() - prev_size; 751 } 752 753 Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, 754 Debug symbol_debug_type, 755 Visibility symbol_visibility, 756 uint32_t &start_idx) { 757 std::lock_guard<std::recursive_mutex> guard(m_mutex); 758 759 const size_t count = m_symbols.size(); 760 for (size_t idx = start_idx; idx < count; ++idx) { 761 if (symbol_type == eSymbolTypeAny || 762 m_symbols[idx].GetType() == symbol_type) { 763 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { 764 start_idx = idx; 765 return &m_symbols[idx]; 766 } 767 } 768 } 769 return nullptr; 770 } 771 772 size_t 773 Symtab::FindAllSymbolsWithNameAndType(const ConstString &name, 774 SymbolType symbol_type, 775 std::vector<uint32_t> &symbol_indexes) { 776 std::lock_guard<std::recursive_mutex> guard(m_mutex); 777 778 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 779 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 780 // Initialize all of the lookup by name indexes before converting NAME to a 781 // uniqued string NAME_STR below. 782 if (!m_name_indexes_computed) 783 InitNameIndexes(); 784 785 if (name) { 786 // The string table did have a string that matched, but we need to check 787 // the symbols and match the symbol_type if any was given. 788 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 789 } 790 return symbol_indexes.size(); 791 } 792 793 size_t Symtab::FindAllSymbolsWithNameAndType( 794 const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, 795 Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { 796 std::lock_guard<std::recursive_mutex> guard(m_mutex); 797 798 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 799 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 800 // Initialize all of the lookup by name indexes before converting NAME to a 801 // uniqued string NAME_STR below. 802 if (!m_name_indexes_computed) 803 InitNameIndexes(); 804 805 if (name) { 806 // The string table did have a string that matched, but we need to check 807 // the symbols and match the symbol_type if any was given. 808 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 809 symbol_visibility, symbol_indexes); 810 } 811 return symbol_indexes.size(); 812 } 813 814 size_t Symtab::FindAllSymbolsMatchingRexExAndType( 815 const RegularExpression ®ex, SymbolType symbol_type, 816 Debug symbol_debug_type, Visibility symbol_visibility, 817 std::vector<uint32_t> &symbol_indexes) { 818 std::lock_guard<std::recursive_mutex> guard(m_mutex); 819 820 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, 821 symbol_visibility, symbol_indexes); 822 return symbol_indexes.size(); 823 } 824 825 Symbol *Symtab::FindFirstSymbolWithNameAndType(const ConstString &name, 826 SymbolType symbol_type, 827 Debug symbol_debug_type, 828 Visibility symbol_visibility) { 829 std::lock_guard<std::recursive_mutex> guard(m_mutex); 830 831 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 832 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 833 if (!m_name_indexes_computed) 834 InitNameIndexes(); 835 836 if (name) { 837 std::vector<uint32_t> matching_indexes; 838 // The string table did have a string that matched, but we need to check 839 // the symbols and match the symbol_type if any was given. 840 if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 841 symbol_visibility, 842 matching_indexes)) { 843 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 844 for (pos = matching_indexes.begin(); pos != end; ++pos) { 845 Symbol *symbol = SymbolAtIndex(*pos); 846 847 if (symbol->Compare(name, symbol_type)) 848 return symbol; 849 } 850 } 851 } 852 return nullptr; 853 } 854 855 typedef struct { 856 const Symtab *symtab; 857 const addr_t file_addr; 858 Symbol *match_symbol; 859 const uint32_t *match_index_ptr; 860 addr_t match_offset; 861 } SymbolSearchInfo; 862 863 // Add all the section file start address & size to the RangeVector, recusively 864 // adding any children sections. 865 static void AddSectionsToRangeMap(SectionList *sectlist, 866 RangeVector<addr_t, addr_t> §ion_ranges) { 867 const int num_sections = sectlist->GetNumSections(0); 868 for (int i = 0; i < num_sections; i++) { 869 SectionSP sect_sp = sectlist->GetSectionAtIndex(i); 870 if (sect_sp) { 871 SectionList &child_sectlist = sect_sp->GetChildren(); 872 873 // If this section has children, add the children to the RangeVector. 874 // Else add this section to the RangeVector. 875 if (child_sectlist.GetNumSections(0) > 0) { 876 AddSectionsToRangeMap(&child_sectlist, section_ranges); 877 } else { 878 size_t size = sect_sp->GetByteSize(); 879 if (size > 0) { 880 addr_t base_addr = sect_sp->GetFileAddress(); 881 RangeVector<addr_t, addr_t>::Entry entry; 882 entry.SetRangeBase(base_addr); 883 entry.SetByteSize(size); 884 section_ranges.Append(entry); 885 } 886 } 887 } 888 } 889 } 890 891 void Symtab::InitAddressIndexes() { 892 // Protected function, no need to lock mutex... 893 if (!m_file_addr_to_index_computed && !m_symbols.empty()) { 894 m_file_addr_to_index_computed = true; 895 896 FileRangeToIndexMap::Entry entry; 897 const_iterator begin = m_symbols.begin(); 898 const_iterator end = m_symbols.end(); 899 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 900 if (pos->ValueIsAddress()) { 901 entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); 902 entry.SetByteSize(pos->GetByteSize()); 903 entry.data = std::distance(begin, pos); 904 m_file_addr_to_index.Append(entry); 905 } 906 } 907 const size_t num_entries = m_file_addr_to_index.GetSize(); 908 if (num_entries > 0) { 909 m_file_addr_to_index.Sort(); 910 911 // Create a RangeVector with the start & size of all the sections for 912 // this objfile. We'll need to check this for any FileRangeToIndexMap 913 // entries with an uninitialized size, which could potentially be a large 914 // number so reconstituting the weak pointer is busywork when it is 915 // invariant information. 916 SectionList *sectlist = m_objfile->GetSectionList(); 917 RangeVector<addr_t, addr_t> section_ranges; 918 if (sectlist) { 919 AddSectionsToRangeMap(sectlist, section_ranges); 920 section_ranges.Sort(); 921 } 922 923 // Iterate through the FileRangeToIndexMap and fill in the size for any 924 // entries that didn't already have a size from the Symbol (e.g. if we 925 // have a plain linker symbol with an address only, instead of debug info 926 // where we get an address and a size and a type, etc.) 927 for (size_t i = 0; i < num_entries; i++) { 928 FileRangeToIndexMap::Entry *entry = 929 m_file_addr_to_index.GetMutableEntryAtIndex(i); 930 if (entry->GetByteSize() == 0) { 931 addr_t curr_base_addr = entry->GetRangeBase(); 932 const RangeVector<addr_t, addr_t>::Entry *containing_section = 933 section_ranges.FindEntryThatContains(curr_base_addr); 934 935 // Use the end of the section as the default max size of the symbol 936 addr_t sym_size = 0; 937 if (containing_section) { 938 sym_size = 939 containing_section->GetByteSize() - 940 (entry->GetRangeBase() - containing_section->GetRangeBase()); 941 } 942 943 for (size_t j = i; j < num_entries; j++) { 944 FileRangeToIndexMap::Entry *next_entry = 945 m_file_addr_to_index.GetMutableEntryAtIndex(j); 946 addr_t next_base_addr = next_entry->GetRangeBase(); 947 if (next_base_addr > curr_base_addr) { 948 addr_t size_to_next_symbol = next_base_addr - curr_base_addr; 949 950 // Take the difference between this symbol and the next one as 951 // its size, if it is less than the size of the section. 952 if (sym_size == 0 || size_to_next_symbol < sym_size) { 953 sym_size = size_to_next_symbol; 954 } 955 break; 956 } 957 } 958 959 if (sym_size > 0) { 960 entry->SetByteSize(sym_size); 961 Symbol &symbol = m_symbols[entry->data]; 962 symbol.SetByteSize(sym_size); 963 symbol.SetSizeIsSynthesized(true); 964 } 965 } 966 } 967 968 // Sort again in case the range size changes the ordering 969 m_file_addr_to_index.Sort(); 970 } 971 } 972 } 973 974 void Symtab::CalculateSymbolSizes() { 975 std::lock_guard<std::recursive_mutex> guard(m_mutex); 976 977 if (!m_symbols.empty()) { 978 if (!m_file_addr_to_index_computed) 979 InitAddressIndexes(); 980 981 const size_t num_entries = m_file_addr_to_index.GetSize(); 982 983 for (size_t i = 0; i < num_entries; ++i) { 984 // The entries in the m_file_addr_to_index have calculated the sizes 985 // already so we will use this size if we need to. 986 const FileRangeToIndexMap::Entry &entry = 987 m_file_addr_to_index.GetEntryRef(i); 988 989 Symbol &symbol = m_symbols[entry.data]; 990 991 // If the symbol size is already valid, no need to do anything 992 if (symbol.GetByteSizeIsValid()) 993 continue; 994 995 const addr_t range_size = entry.GetByteSize(); 996 if (range_size > 0) { 997 symbol.SetByteSize(range_size); 998 symbol.SetSizeIsSynthesized(true); 999 } 1000 } 1001 } 1002 } 1003 1004 Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { 1005 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1006 if (!m_file_addr_to_index_computed) 1007 InitAddressIndexes(); 1008 1009 const FileRangeToIndexMap::Entry *entry = 1010 m_file_addr_to_index.FindEntryStartsAt(file_addr); 1011 if (entry) { 1012 Symbol *symbol = SymbolAtIndex(entry->data); 1013 if (symbol->GetFileAddress() == file_addr) 1014 return symbol; 1015 } 1016 return nullptr; 1017 } 1018 1019 Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { 1020 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1021 1022 if (!m_file_addr_to_index_computed) 1023 InitAddressIndexes(); 1024 1025 const FileRangeToIndexMap::Entry *entry = 1026 m_file_addr_to_index.FindEntryThatContains(file_addr); 1027 if (entry) { 1028 Symbol *symbol = SymbolAtIndex(entry->data); 1029 if (symbol->ContainsFileAddress(file_addr)) 1030 return symbol; 1031 } 1032 return nullptr; 1033 } 1034 1035 void Symtab::ForEachSymbolContainingFileAddress( 1036 addr_t file_addr, std::function<bool(Symbol *)> const &callback) { 1037 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1038 1039 if (!m_file_addr_to_index_computed) 1040 InitAddressIndexes(); 1041 1042 std::vector<uint32_t> all_addr_indexes; 1043 1044 // Get all symbols with file_addr 1045 const size_t addr_match_count = 1046 m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, 1047 all_addr_indexes); 1048 1049 for (size_t i = 0; i < addr_match_count; ++i) { 1050 Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); 1051 if (symbol->ContainsFileAddress(file_addr)) { 1052 if (!callback(symbol)) 1053 break; 1054 } 1055 } 1056 } 1057 1058 void Symtab::SymbolIndicesToSymbolContextList( 1059 std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { 1060 // No need to protect this call using m_mutex all other method calls are 1061 // already thread safe. 1062 1063 const bool merge_symbol_into_function = true; 1064 size_t num_indices = symbol_indexes.size(); 1065 if (num_indices > 0) { 1066 SymbolContext sc; 1067 sc.module_sp = m_objfile->GetModule(); 1068 for (size_t i = 0; i < num_indices; i++) { 1069 sc.symbol = SymbolAtIndex(symbol_indexes[i]); 1070 if (sc.symbol) 1071 sc_list.AppendIfUnique(sc, merge_symbol_into_function); 1072 } 1073 } 1074 } 1075 1076 size_t Symtab::FindFunctionSymbols(const ConstString &name, 1077 uint32_t name_type_mask, 1078 SymbolContextList &sc_list) { 1079 size_t count = 0; 1080 std::vector<uint32_t> symbol_indexes; 1081 1082 // eFunctionNameTypeAuto should be pre-resolved by a call to 1083 // Module::LookupInfo::LookupInfo() 1084 assert((name_type_mask & eFunctionNameTypeAuto) == 0); 1085 1086 if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { 1087 std::vector<uint32_t> temp_symbol_indexes; 1088 FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); 1089 1090 unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 1091 if (temp_symbol_indexes_size > 0) { 1092 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1093 for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { 1094 SymbolContext sym_ctx; 1095 sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); 1096 if (sym_ctx.symbol) { 1097 switch (sym_ctx.symbol->GetType()) { 1098 case eSymbolTypeCode: 1099 case eSymbolTypeResolver: 1100 case eSymbolTypeReExported: 1101 symbol_indexes.push_back(temp_symbol_indexes[i]); 1102 break; 1103 default: 1104 break; 1105 } 1106 } 1107 } 1108 } 1109 } 1110 1111 if (name_type_mask & eFunctionNameTypeBase) { 1112 // From mangled names we can't tell what is a basename and what is a method 1113 // name, so we just treat them the same 1114 if (!m_name_indexes_computed) 1115 InitNameIndexes(); 1116 1117 if (!m_basename_to_index.IsEmpty()) { 1118 const UniqueCStringMap<uint32_t>::Entry *match; 1119 for (match = m_basename_to_index.FindFirstValueForName(name); 1120 match != nullptr; 1121 match = m_basename_to_index.FindNextValueForName(match)) { 1122 symbol_indexes.push_back(match->value); 1123 } 1124 } 1125 } 1126 1127 if (name_type_mask & eFunctionNameTypeMethod) { 1128 if (!m_name_indexes_computed) 1129 InitNameIndexes(); 1130 1131 if (!m_method_to_index.IsEmpty()) { 1132 const UniqueCStringMap<uint32_t>::Entry *match; 1133 for (match = m_method_to_index.FindFirstValueForName(name); 1134 match != nullptr; 1135 match = m_method_to_index.FindNextValueForName(match)) { 1136 symbol_indexes.push_back(match->value); 1137 } 1138 } 1139 } 1140 1141 if (name_type_mask & eFunctionNameTypeSelector) { 1142 if (!m_name_indexes_computed) 1143 InitNameIndexes(); 1144 1145 if (!m_selector_to_index.IsEmpty()) { 1146 const UniqueCStringMap<uint32_t>::Entry *match; 1147 for (match = m_selector_to_index.FindFirstValueForName(name); 1148 match != nullptr; 1149 match = m_selector_to_index.FindNextValueForName(match)) { 1150 symbol_indexes.push_back(match->value); 1151 } 1152 } 1153 } 1154 1155 if (!symbol_indexes.empty()) { 1156 std::sort(symbol_indexes.begin(), symbol_indexes.end()); 1157 symbol_indexes.erase( 1158 std::unique(symbol_indexes.begin(), symbol_indexes.end()), 1159 symbol_indexes.end()); 1160 count = symbol_indexes.size(); 1161 SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); 1162 } 1163 1164 return count; 1165 } 1166 1167 const Symbol *Symtab::GetParent(Symbol *child_symbol) const { 1168 uint32_t child_idx = GetIndexForSymbol(child_symbol); 1169 if (child_idx != UINT32_MAX && child_idx > 0) { 1170 for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { 1171 const Symbol *symbol = SymbolAtIndex(idx); 1172 const uint32_t sibling_idx = symbol->GetSiblingIndex(); 1173 if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) 1174 return symbol; 1175 } 1176 } 1177 return NULL; 1178 } 1179