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