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 llvm_unreachable("unknown scheme!"); 253 } 254 255 void Symtab::InitNameIndexes() { 256 // Protected function, no need to lock mutex... 257 if (!m_name_indexes_computed) { 258 m_name_indexes_computed = true; 259 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 260 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 261 // Create the name index vector to be able to quickly search by name 262 const size_t num_symbols = m_symbols.size(); 263 #if 1 264 m_name_to_index.Reserve(num_symbols); 265 #else 266 // TODO: benchmark this to see if we save any memory. Otherwise we 267 // will always keep the memory reserved in the vector unless we pull some 268 // STL swap magic and then recopy... 269 uint32_t actual_count = 0; 270 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 271 pos != end; ++pos) { 272 const Mangled &mangled = pos->GetMangled(); 273 if (mangled.GetMangledName()) 274 ++actual_count; 275 276 if (mangled.GetDemangledName()) 277 ++actual_count; 278 } 279 280 m_name_to_index.Reserve(actual_count); 281 #endif 282 283 // The "const char *" in "class_contexts" and backlog::value_type::second 284 // must come from a ConstString::GetCString() 285 std::set<const char *> class_contexts; 286 std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog; 287 backlog.reserve(num_symbols / 2); 288 289 // Instantiation of the demangler is expensive, so better use a single one 290 // for all entries during batch processing. 291 RichManglingContext rmc; 292 NameToIndexMap::Entry entry; 293 294 for (entry.value = 0; entry.value < num_symbols; ++entry.value) { 295 Symbol *symbol = &m_symbols[entry.value]; 296 297 // Don't let trampolines get into the lookup by name map If we ever need 298 // the trampoline symbols to be searchable by name we can remove this and 299 // then possibly add a new bool to any of the Symtab functions that 300 // lookup symbols by name to indicate if they want trampolines. 301 if (symbol->IsTrampoline()) 302 continue; 303 304 // If the symbol's name string matched a Mangled::ManglingScheme, it is 305 // stored in the mangled field. 306 Mangled &mangled = symbol->GetMangled(); 307 entry.cstring = mangled.GetMangledName(); 308 if (entry.cstring) { 309 m_name_to_index.Append(entry); 310 311 if (symbol->ContainsLinkerAnnotations()) { 312 // If the symbol has linker annotations, also add the version without 313 // the annotations. 314 entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( 315 entry.cstring.GetStringRef())); 316 m_name_to_index.Append(entry); 317 } 318 319 const SymbolType type = symbol->GetType(); 320 if (type == eSymbolTypeCode || type == eSymbolTypeResolver) { 321 if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name)) 322 RegisterMangledNameEntry(entry, class_contexts, backlog, rmc); 323 } 324 } 325 326 // Symbol name strings that didn't match a Mangled::ManglingScheme, are 327 // stored in the demangled field. 328 entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()); 329 if (entry.cstring) { 330 m_name_to_index.Append(entry); 331 332 if (symbol->ContainsLinkerAnnotations()) { 333 // If the symbol has linker annotations, also add the version without 334 // the annotations. 335 entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( 336 entry.cstring.GetStringRef())); 337 m_name_to_index.Append(entry); 338 } 339 } 340 341 // If the demangled name turns out to be an ObjC name, and is a category 342 // name, add the version without categories to the index too. 343 ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true); 344 if (objc_method.IsValid(true)) { 345 entry.cstring = objc_method.GetSelector(); 346 m_selector_to_index.Append(entry); 347 348 ConstString objc_method_no_category( 349 objc_method.GetFullNameWithoutCategory(true)); 350 if (objc_method_no_category) { 351 entry.cstring = objc_method_no_category; 352 m_name_to_index.Append(entry); 353 } 354 } 355 } 356 357 for (const auto &record : backlog) { 358 RegisterBacklogEntry(record.first, record.second, class_contexts); 359 } 360 361 m_name_to_index.Sort(); 362 m_name_to_index.SizeToFit(); 363 m_selector_to_index.Sort(); 364 m_selector_to_index.SizeToFit(); 365 m_basename_to_index.Sort(); 366 m_basename_to_index.SizeToFit(); 367 m_method_to_index.Sort(); 368 m_method_to_index.SizeToFit(); 369 } 370 } 371 372 void Symtab::RegisterMangledNameEntry( 373 NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts, 374 std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog, 375 RichManglingContext &rmc) { 376 // Only register functions that have a base name. 377 rmc.ParseFunctionBaseName(); 378 llvm::StringRef base_name = rmc.GetBufferRef(); 379 if (base_name.empty()) 380 return; 381 382 // The base name will be our entry's name. 383 entry.cstring = ConstString(base_name); 384 385 rmc.ParseFunctionDeclContextName(); 386 llvm::StringRef decl_context = rmc.GetBufferRef(); 387 388 // Register functions with no context. 389 if (decl_context.empty()) { 390 // This has to be a basename 391 m_basename_to_index.Append(entry); 392 // If there is no context (no namespaces or class scopes that come before 393 // the function name) then this also could be a fullname. 394 m_name_to_index.Append(entry); 395 return; 396 } 397 398 // Make sure we have a pool-string pointer and see if we already know the 399 // context name. 400 const char *decl_context_ccstr = ConstString(decl_context).GetCString(); 401 auto it = class_contexts.find(decl_context_ccstr); 402 403 // Register constructors and destructors. They are methods and create 404 // declaration contexts. 405 if (rmc.IsCtorOrDtor()) { 406 m_method_to_index.Append(entry); 407 if (it == class_contexts.end()) 408 class_contexts.insert(it, decl_context_ccstr); 409 return; 410 } 411 412 // Register regular methods with a known declaration context. 413 if (it != class_contexts.end()) { 414 m_method_to_index.Append(entry); 415 return; 416 } 417 418 // Regular methods in unknown declaration contexts are put to the backlog. We 419 // will revisit them once we processed all remaining symbols. 420 backlog.push_back(std::make_pair(entry, decl_context_ccstr)); 421 } 422 423 void Symtab::RegisterBacklogEntry( 424 const NameToIndexMap::Entry &entry, const char *decl_context, 425 const std::set<const char *> &class_contexts) { 426 auto it = class_contexts.find(decl_context); 427 if (it != class_contexts.end()) { 428 m_method_to_index.Append(entry); 429 } else { 430 // If we got here, we have something that had a context (was inside 431 // a namespace or class) yet we don't know the entry 432 m_method_to_index.Append(entry); 433 m_basename_to_index.Append(entry); 434 } 435 } 436 437 void Symtab::PreloadSymbols() { 438 std::lock_guard<std::recursive_mutex> guard(m_mutex); 439 InitNameIndexes(); 440 } 441 442 void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, 443 bool add_demangled, bool add_mangled, 444 NameToIndexMap &name_to_index_map) const { 445 if (add_demangled || add_mangled) { 446 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 447 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 448 std::lock_guard<std::recursive_mutex> guard(m_mutex); 449 450 // Create the name index vector to be able to quickly search by name 451 NameToIndexMap::Entry entry; 452 const size_t num_indexes = indexes.size(); 453 for (size_t i = 0; i < num_indexes; ++i) { 454 entry.value = indexes[i]; 455 assert(i < m_symbols.size()); 456 const Symbol *symbol = &m_symbols[entry.value]; 457 458 const Mangled &mangled = symbol->GetMangled(); 459 if (add_demangled) { 460 entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()); 461 if (entry.cstring) 462 name_to_index_map.Append(entry); 463 } 464 465 if (add_mangled) { 466 entry.cstring = mangled.GetMangledName(); 467 if (entry.cstring) 468 name_to_index_map.Append(entry); 469 } 470 } 471 } 472 } 473 474 uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 475 std::vector<uint32_t> &indexes, 476 uint32_t start_idx, 477 uint32_t end_index) const { 478 std::lock_guard<std::recursive_mutex> guard(m_mutex); 479 480 uint32_t prev_size = indexes.size(); 481 482 const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 483 484 for (uint32_t i = start_idx; i < count; ++i) { 485 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 486 indexes.push_back(i); 487 } 488 489 return indexes.size() - prev_size; 490 } 491 492 uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue( 493 SymbolType symbol_type, uint32_t flags_value, 494 std::vector<uint32_t> &indexes, uint32_t start_idx, 495 uint32_t end_index) const { 496 std::lock_guard<std::recursive_mutex> guard(m_mutex); 497 498 uint32_t prev_size = indexes.size(); 499 500 const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 501 502 for (uint32_t i = start_idx; i < count; ++i) { 503 if ((symbol_type == eSymbolTypeAny || 504 m_symbols[i].GetType() == symbol_type) && 505 m_symbols[i].GetFlags() == flags_value) 506 indexes.push_back(i); 507 } 508 509 return indexes.size() - prev_size; 510 } 511 512 uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, 513 Debug symbol_debug_type, 514 Visibility symbol_visibility, 515 std::vector<uint32_t> &indexes, 516 uint32_t start_idx, 517 uint32_t end_index) const { 518 std::lock_guard<std::recursive_mutex> guard(m_mutex); 519 520 uint32_t prev_size = indexes.size(); 521 522 const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); 523 524 for (uint32_t i = start_idx; i < count; ++i) { 525 if (symbol_type == eSymbolTypeAny || 526 m_symbols[i].GetType() == symbol_type) { 527 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 528 indexes.push_back(i); 529 } 530 } 531 532 return indexes.size() - prev_size; 533 } 534 535 uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const { 536 if (!m_symbols.empty()) { 537 const Symbol *first_symbol = &m_symbols[0]; 538 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 539 return symbol - first_symbol; 540 } 541 return UINT32_MAX; 542 } 543 544 struct SymbolSortInfo { 545 const bool sort_by_load_addr; 546 const Symbol *symbols; 547 }; 548 549 namespace { 550 struct SymbolIndexComparator { 551 const std::vector<Symbol> &symbols; 552 std::vector<lldb::addr_t> &addr_cache; 553 554 // Getting from the symbol to the Address to the File Address involves some 555 // work. Since there are potentially many symbols here, and we're using this 556 // for sorting so we're going to be computing the address many times, cache 557 // that in addr_cache. The array passed in has to be the same size as the 558 // symbols array passed into the member variable symbols, and should be 559 // initialized with LLDB_INVALID_ADDRESS. 560 // NOTE: You have to make addr_cache externally and pass it in because 561 // std::stable_sort 562 // makes copies of the comparator it is initially passed in, and you end up 563 // spending huge amounts of time copying this array... 564 565 SymbolIndexComparator(const std::vector<Symbol> &s, 566 std::vector<lldb::addr_t> &a) 567 : symbols(s), addr_cache(a) { 568 assert(symbols.size() == addr_cache.size()); 569 } 570 bool operator()(uint32_t index_a, uint32_t index_b) { 571 addr_t value_a = addr_cache[index_a]; 572 if (value_a == LLDB_INVALID_ADDRESS) { 573 value_a = symbols[index_a].GetAddressRef().GetFileAddress(); 574 addr_cache[index_a] = value_a; 575 } 576 577 addr_t value_b = addr_cache[index_b]; 578 if (value_b == LLDB_INVALID_ADDRESS) { 579 value_b = symbols[index_b].GetAddressRef().GetFileAddress(); 580 addr_cache[index_b] = value_b; 581 } 582 583 if (value_a == value_b) { 584 // The if the values are equal, use the original symbol user ID 585 lldb::user_id_t uid_a = symbols[index_a].GetID(); 586 lldb::user_id_t uid_b = symbols[index_b].GetID(); 587 if (uid_a < uid_b) 588 return true; 589 if (uid_a > uid_b) 590 return false; 591 return false; 592 } else if (value_a < value_b) 593 return true; 594 595 return false; 596 } 597 }; 598 } 599 600 void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, 601 bool remove_duplicates) const { 602 std::lock_guard<std::recursive_mutex> guard(m_mutex); 603 604 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 605 Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 606 // No need to sort if we have zero or one items... 607 if (indexes.size() <= 1) 608 return; 609 610 // Sort the indexes in place using std::stable_sort. 611 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for 612 // performance, 613 // not correctness. The indexes vector tends to be "close" to sorted, which 614 // the stable sort handles better. 615 616 std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 617 618 SymbolIndexComparator comparator(m_symbols, addr_cache); 619 std::stable_sort(indexes.begin(), indexes.end(), comparator); 620 621 // Remove any duplicates if requested 622 if (remove_duplicates) { 623 auto last = std::unique(indexes.begin(), indexes.end()); 624 indexes.erase(last, indexes.end()); 625 } 626 } 627 628 uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, 629 std::vector<uint32_t> &indexes) { 630 std::lock_guard<std::recursive_mutex> guard(m_mutex); 631 632 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 633 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 634 if (symbol_name) { 635 if (!m_name_indexes_computed) 636 InitNameIndexes(); 637 638 return m_name_to_index.GetValues(symbol_name, indexes); 639 } 640 return 0; 641 } 642 643 uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, 644 Debug symbol_debug_type, 645 Visibility symbol_visibility, 646 std::vector<uint32_t> &indexes) { 647 std::lock_guard<std::recursive_mutex> guard(m_mutex); 648 649 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 650 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 651 if (symbol_name) { 652 const size_t old_size = indexes.size(); 653 if (!m_name_indexes_computed) 654 InitNameIndexes(); 655 656 std::vector<uint32_t> all_name_indexes; 657 const size_t name_match_count = 658 m_name_to_index.GetValues(symbol_name, all_name_indexes); 659 for (size_t i = 0; i < name_match_count; ++i) { 660 if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, 661 symbol_visibility)) 662 indexes.push_back(all_name_indexes[i]); 663 } 664 return indexes.size() - old_size; 665 } 666 return 0; 667 } 668 669 uint32_t 670 Symtab::AppendSymbolIndexesWithNameAndType(const ConstString &symbol_name, 671 SymbolType symbol_type, 672 std::vector<uint32_t> &indexes) { 673 std::lock_guard<std::recursive_mutex> guard(m_mutex); 674 675 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { 676 std::vector<uint32_t>::iterator pos = indexes.begin(); 677 while (pos != indexes.end()) { 678 if (symbol_type == eSymbolTypeAny || 679 m_symbols[*pos].GetType() == symbol_type) 680 ++pos; 681 else 682 pos = indexes.erase(pos); 683 } 684 } 685 return indexes.size(); 686 } 687 688 uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 689 const ConstString &symbol_name, SymbolType symbol_type, 690 Debug symbol_debug_type, Visibility symbol_visibility, 691 std::vector<uint32_t> &indexes) { 692 std::lock_guard<std::recursive_mutex> guard(m_mutex); 693 694 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, 695 symbol_visibility, indexes) > 0) { 696 std::vector<uint32_t>::iterator pos = indexes.begin(); 697 while (pos != indexes.end()) { 698 if (symbol_type == eSymbolTypeAny || 699 m_symbols[*pos].GetType() == symbol_type) 700 ++pos; 701 else 702 pos = indexes.erase(pos); 703 } 704 } 705 return indexes.size(); 706 } 707 708 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 709 const RegularExpression ®exp, SymbolType symbol_type, 710 std::vector<uint32_t> &indexes) { 711 std::lock_guard<std::recursive_mutex> guard(m_mutex); 712 713 uint32_t prev_size = indexes.size(); 714 uint32_t sym_end = m_symbols.size(); 715 716 for (uint32_t i = 0; i < sym_end; i++) { 717 if (symbol_type == eSymbolTypeAny || 718 m_symbols[i].GetType() == symbol_type) { 719 const char *name = m_symbols[i].GetName().AsCString(); 720 if (name) { 721 if (regexp.Execute(name)) 722 indexes.push_back(i); 723 } 724 } 725 } 726 return indexes.size() - prev_size; 727 } 728 729 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 730 const RegularExpression ®exp, SymbolType symbol_type, 731 Debug symbol_debug_type, Visibility symbol_visibility, 732 std::vector<uint32_t> &indexes) { 733 std::lock_guard<std::recursive_mutex> guard(m_mutex); 734 735 uint32_t prev_size = indexes.size(); 736 uint32_t sym_end = m_symbols.size(); 737 738 for (uint32_t i = 0; i < sym_end; i++) { 739 if (symbol_type == eSymbolTypeAny || 740 m_symbols[i].GetType() == symbol_type) { 741 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) 742 continue; 743 744 const char *name = m_symbols[i].GetName().AsCString(); 745 if (name) { 746 if (regexp.Execute(name)) 747 indexes.push_back(i); 748 } 749 } 750 } 751 return indexes.size() - prev_size; 752 } 753 754 Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, 755 Debug symbol_debug_type, 756 Visibility symbol_visibility, 757 uint32_t &start_idx) { 758 std::lock_guard<std::recursive_mutex> guard(m_mutex); 759 760 const size_t count = m_symbols.size(); 761 for (size_t idx = start_idx; idx < count; ++idx) { 762 if (symbol_type == eSymbolTypeAny || 763 m_symbols[idx].GetType() == symbol_type) { 764 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { 765 start_idx = idx; 766 return &m_symbols[idx]; 767 } 768 } 769 } 770 return nullptr; 771 } 772 773 size_t 774 Symtab::FindAllSymbolsWithNameAndType(const ConstString &name, 775 SymbolType symbol_type, 776 std::vector<uint32_t> &symbol_indexes) { 777 std::lock_guard<std::recursive_mutex> guard(m_mutex); 778 779 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 780 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 781 // Initialize all of the lookup by name indexes before converting NAME to a 782 // uniqued string NAME_STR below. 783 if (!m_name_indexes_computed) 784 InitNameIndexes(); 785 786 if (name) { 787 // The string table did have a string that matched, but we need to check 788 // the symbols and match the symbol_type if any was given. 789 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 790 } 791 return symbol_indexes.size(); 792 } 793 794 size_t Symtab::FindAllSymbolsWithNameAndType( 795 const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, 796 Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { 797 std::lock_guard<std::recursive_mutex> guard(m_mutex); 798 799 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 800 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 801 // Initialize all of the lookup by name indexes before converting NAME to a 802 // uniqued string NAME_STR below. 803 if (!m_name_indexes_computed) 804 InitNameIndexes(); 805 806 if (name) { 807 // The string table did have a string that matched, but we need to check 808 // the symbols and match the symbol_type if any was given. 809 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 810 symbol_visibility, symbol_indexes); 811 } 812 return symbol_indexes.size(); 813 } 814 815 size_t Symtab::FindAllSymbolsMatchingRexExAndType( 816 const RegularExpression ®ex, SymbolType symbol_type, 817 Debug symbol_debug_type, Visibility symbol_visibility, 818 std::vector<uint32_t> &symbol_indexes) { 819 std::lock_guard<std::recursive_mutex> guard(m_mutex); 820 821 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, 822 symbol_visibility, symbol_indexes); 823 return symbol_indexes.size(); 824 } 825 826 Symbol *Symtab::FindFirstSymbolWithNameAndType(const ConstString &name, 827 SymbolType symbol_type, 828 Debug symbol_debug_type, 829 Visibility symbol_visibility) { 830 std::lock_guard<std::recursive_mutex> guard(m_mutex); 831 832 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 833 Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION); 834 if (!m_name_indexes_computed) 835 InitNameIndexes(); 836 837 if (name) { 838 std::vector<uint32_t> matching_indexes; 839 // The string table did have a string that matched, but we need to check 840 // the symbols and match the symbol_type if any was given. 841 if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, 842 symbol_visibility, 843 matching_indexes)) { 844 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 845 for (pos = matching_indexes.begin(); pos != end; ++pos) { 846 Symbol *symbol = SymbolAtIndex(*pos); 847 848 if (symbol->Compare(name, symbol_type)) 849 return symbol; 850 } 851 } 852 } 853 return nullptr; 854 } 855 856 typedef struct { 857 const Symtab *symtab; 858 const addr_t file_addr; 859 Symbol *match_symbol; 860 const uint32_t *match_index_ptr; 861 addr_t match_offset; 862 } SymbolSearchInfo; 863 864 // Add all the section file start address & size to the RangeVector, recusively 865 // adding any children sections. 866 static void AddSectionsToRangeMap(SectionList *sectlist, 867 RangeVector<addr_t, addr_t> §ion_ranges) { 868 const int num_sections = sectlist->GetNumSections(0); 869 for (int i = 0; i < num_sections; i++) { 870 SectionSP sect_sp = sectlist->GetSectionAtIndex(i); 871 if (sect_sp) { 872 SectionList &child_sectlist = sect_sp->GetChildren(); 873 874 // If this section has children, add the children to the RangeVector. 875 // Else add this section to the RangeVector. 876 if (child_sectlist.GetNumSections(0) > 0) { 877 AddSectionsToRangeMap(&child_sectlist, section_ranges); 878 } else { 879 size_t size = sect_sp->GetByteSize(); 880 if (size > 0) { 881 addr_t base_addr = sect_sp->GetFileAddress(); 882 RangeVector<addr_t, addr_t>::Entry entry; 883 entry.SetRangeBase(base_addr); 884 entry.SetByteSize(size); 885 section_ranges.Append(entry); 886 } 887 } 888 } 889 } 890 } 891 892 void Symtab::InitAddressIndexes() { 893 // Protected function, no need to lock mutex... 894 if (!m_file_addr_to_index_computed && !m_symbols.empty()) { 895 m_file_addr_to_index_computed = true; 896 897 FileRangeToIndexMap::Entry entry; 898 const_iterator begin = m_symbols.begin(); 899 const_iterator end = m_symbols.end(); 900 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { 901 if (pos->ValueIsAddress()) { 902 entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); 903 entry.SetByteSize(pos->GetByteSize()); 904 entry.data = std::distance(begin, pos); 905 m_file_addr_to_index.Append(entry); 906 } 907 } 908 const size_t num_entries = m_file_addr_to_index.GetSize(); 909 if (num_entries > 0) { 910 m_file_addr_to_index.Sort(); 911 912 // Create a RangeVector with the start & size of all the sections for 913 // this objfile. We'll need to check this for any FileRangeToIndexMap 914 // entries with an uninitialized size, which could potentially be a large 915 // number so reconstituting the weak pointer is busywork when it is 916 // invariant information. 917 SectionList *sectlist = m_objfile->GetSectionList(); 918 RangeVector<addr_t, addr_t> section_ranges; 919 if (sectlist) { 920 AddSectionsToRangeMap(sectlist, section_ranges); 921 section_ranges.Sort(); 922 } 923 924 // Iterate through the FileRangeToIndexMap and fill in the size for any 925 // entries that didn't already have a size from the Symbol (e.g. if we 926 // have a plain linker symbol with an address only, instead of debug info 927 // where we get an address and a size and a type, etc.) 928 for (size_t i = 0; i < num_entries; i++) { 929 FileRangeToIndexMap::Entry *entry = 930 m_file_addr_to_index.GetMutableEntryAtIndex(i); 931 if (entry->GetByteSize() == 0) { 932 addr_t curr_base_addr = entry->GetRangeBase(); 933 const RangeVector<addr_t, addr_t>::Entry *containing_section = 934 section_ranges.FindEntryThatContains(curr_base_addr); 935 936 // Use the end of the section as the default max size of the symbol 937 addr_t sym_size = 0; 938 if (containing_section) { 939 sym_size = 940 containing_section->GetByteSize() - 941 (entry->GetRangeBase() - containing_section->GetRangeBase()); 942 } 943 944 for (size_t j = i; j < num_entries; j++) { 945 FileRangeToIndexMap::Entry *next_entry = 946 m_file_addr_to_index.GetMutableEntryAtIndex(j); 947 addr_t next_base_addr = next_entry->GetRangeBase(); 948 if (next_base_addr > curr_base_addr) { 949 addr_t size_to_next_symbol = next_base_addr - curr_base_addr; 950 951 // Take the difference between this symbol and the next one as 952 // its size, if it is less than the size of the section. 953 if (sym_size == 0 || size_to_next_symbol < sym_size) { 954 sym_size = size_to_next_symbol; 955 } 956 break; 957 } 958 } 959 960 if (sym_size > 0) { 961 entry->SetByteSize(sym_size); 962 Symbol &symbol = m_symbols[entry->data]; 963 symbol.SetByteSize(sym_size); 964 symbol.SetSizeIsSynthesized(true); 965 } 966 } 967 } 968 969 // Sort again in case the range size changes the ordering 970 m_file_addr_to_index.Sort(); 971 } 972 } 973 } 974 975 void Symtab::CalculateSymbolSizes() { 976 std::lock_guard<std::recursive_mutex> guard(m_mutex); 977 978 if (!m_symbols.empty()) { 979 if (!m_file_addr_to_index_computed) 980 InitAddressIndexes(); 981 982 const size_t num_entries = m_file_addr_to_index.GetSize(); 983 984 for (size_t i = 0; i < num_entries; ++i) { 985 // The entries in the m_file_addr_to_index have calculated the sizes 986 // already so we will use this size if we need to. 987 const FileRangeToIndexMap::Entry &entry = 988 m_file_addr_to_index.GetEntryRef(i); 989 990 Symbol &symbol = m_symbols[entry.data]; 991 992 // If the symbol size is already valid, no need to do anything 993 if (symbol.GetByteSizeIsValid()) 994 continue; 995 996 const addr_t range_size = entry.GetByteSize(); 997 if (range_size > 0) { 998 symbol.SetByteSize(range_size); 999 symbol.SetSizeIsSynthesized(true); 1000 } 1001 } 1002 } 1003 } 1004 1005 Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { 1006 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1007 if (!m_file_addr_to_index_computed) 1008 InitAddressIndexes(); 1009 1010 const FileRangeToIndexMap::Entry *entry = 1011 m_file_addr_to_index.FindEntryStartsAt(file_addr); 1012 if (entry) { 1013 Symbol *symbol = SymbolAtIndex(entry->data); 1014 if (symbol->GetFileAddress() == file_addr) 1015 return symbol; 1016 } 1017 return nullptr; 1018 } 1019 1020 Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { 1021 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1022 1023 if (!m_file_addr_to_index_computed) 1024 InitAddressIndexes(); 1025 1026 const FileRangeToIndexMap::Entry *entry = 1027 m_file_addr_to_index.FindEntryThatContains(file_addr); 1028 if (entry) { 1029 Symbol *symbol = SymbolAtIndex(entry->data); 1030 if (symbol->ContainsFileAddress(file_addr)) 1031 return symbol; 1032 } 1033 return nullptr; 1034 } 1035 1036 void Symtab::ForEachSymbolContainingFileAddress( 1037 addr_t file_addr, std::function<bool(Symbol *)> const &callback) { 1038 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1039 1040 if (!m_file_addr_to_index_computed) 1041 InitAddressIndexes(); 1042 1043 std::vector<uint32_t> all_addr_indexes; 1044 1045 // Get all symbols with file_addr 1046 const size_t addr_match_count = 1047 m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, 1048 all_addr_indexes); 1049 1050 for (size_t i = 0; i < addr_match_count; ++i) { 1051 Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); 1052 if (symbol->ContainsFileAddress(file_addr)) { 1053 if (!callback(symbol)) 1054 break; 1055 } 1056 } 1057 } 1058 1059 void Symtab::SymbolIndicesToSymbolContextList( 1060 std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { 1061 // No need to protect this call using m_mutex all other method calls are 1062 // already thread safe. 1063 1064 const bool merge_symbol_into_function = true; 1065 size_t num_indices = symbol_indexes.size(); 1066 if (num_indices > 0) { 1067 SymbolContext sc; 1068 sc.module_sp = m_objfile->GetModule(); 1069 for (size_t i = 0; i < num_indices; i++) { 1070 sc.symbol = SymbolAtIndex(symbol_indexes[i]); 1071 if (sc.symbol) 1072 sc_list.AppendIfUnique(sc, merge_symbol_into_function); 1073 } 1074 } 1075 } 1076 1077 size_t Symtab::FindFunctionSymbols(const ConstString &name, 1078 uint32_t name_type_mask, 1079 SymbolContextList &sc_list) { 1080 size_t count = 0; 1081 std::vector<uint32_t> symbol_indexes; 1082 1083 // eFunctionNameTypeAuto should be pre-resolved by a call to 1084 // Module::LookupInfo::LookupInfo() 1085 assert((name_type_mask & eFunctionNameTypeAuto) == 0); 1086 1087 if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { 1088 std::vector<uint32_t> temp_symbol_indexes; 1089 FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); 1090 1091 unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 1092 if (temp_symbol_indexes_size > 0) { 1093 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1094 for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { 1095 SymbolContext sym_ctx; 1096 sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); 1097 if (sym_ctx.symbol) { 1098 switch (sym_ctx.symbol->GetType()) { 1099 case eSymbolTypeCode: 1100 case eSymbolTypeResolver: 1101 case eSymbolTypeReExported: 1102 symbol_indexes.push_back(temp_symbol_indexes[i]); 1103 break; 1104 default: 1105 break; 1106 } 1107 } 1108 } 1109 } 1110 } 1111 1112 if (name_type_mask & eFunctionNameTypeBase) { 1113 // From mangled names we can't tell what is a basename and what is a method 1114 // name, so we just treat them the same 1115 if (!m_name_indexes_computed) 1116 InitNameIndexes(); 1117 1118 if (!m_basename_to_index.IsEmpty()) { 1119 const UniqueCStringMap<uint32_t>::Entry *match; 1120 for (match = m_basename_to_index.FindFirstValueForName(name); 1121 match != nullptr; 1122 match = m_basename_to_index.FindNextValueForName(match)) { 1123 symbol_indexes.push_back(match->value); 1124 } 1125 } 1126 } 1127 1128 if (name_type_mask & eFunctionNameTypeMethod) { 1129 if (!m_name_indexes_computed) 1130 InitNameIndexes(); 1131 1132 if (!m_method_to_index.IsEmpty()) { 1133 const UniqueCStringMap<uint32_t>::Entry *match; 1134 for (match = m_method_to_index.FindFirstValueForName(name); 1135 match != nullptr; 1136 match = m_method_to_index.FindNextValueForName(match)) { 1137 symbol_indexes.push_back(match->value); 1138 } 1139 } 1140 } 1141 1142 if (name_type_mask & eFunctionNameTypeSelector) { 1143 if (!m_name_indexes_computed) 1144 InitNameIndexes(); 1145 1146 if (!m_selector_to_index.IsEmpty()) { 1147 const UniqueCStringMap<uint32_t>::Entry *match; 1148 for (match = m_selector_to_index.FindFirstValueForName(name); 1149 match != nullptr; 1150 match = m_selector_to_index.FindNextValueForName(match)) { 1151 symbol_indexes.push_back(match->value); 1152 } 1153 } 1154 } 1155 1156 if (!symbol_indexes.empty()) { 1157 std::sort(symbol_indexes.begin(), symbol_indexes.end()); 1158 symbol_indexes.erase( 1159 std::unique(symbol_indexes.begin(), symbol_indexes.end()), 1160 symbol_indexes.end()); 1161 count = symbol_indexes.size(); 1162 SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); 1163 } 1164 1165 return count; 1166 } 1167 1168 const Symbol *Symtab::GetParent(Symbol *child_symbol) const { 1169 uint32_t child_idx = GetIndexForSymbol(child_symbol); 1170 if (child_idx != UINT32_MAX && child_idx > 0) { 1171 for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { 1172 const Symbol *symbol = SymbolAtIndex(idx); 1173 const uint32_t sibling_idx = symbol->GetSiblingIndex(); 1174 if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) 1175 return symbol; 1176 } 1177 } 1178 return NULL; 1179 } 1180