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