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