Symtab.cpp revision 36da2aa6dc5ad9994b638ed09eb81c44cc05540b
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 20using namespace lldb; 21using namespace lldb_private; 22 23 24 25Symtab::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 36Symtab::~Symtab() 37{ 38} 39 40void 41Symtab::Reserve(size_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 48Symbol * 49Symtab::Resize(size_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 57uint32_t 58Symtab::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 71size_t 72Symtab::GetNumSymbols() const 73{ 74 Mutex::Locker locker (m_mutex); 75 return m_symbols.size(); 76} 77 78void 79Symtab::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 size_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 165void 166Symtab::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 size_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 194void 195Symtab::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 206static int 207CompareSymbolID (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 218Symbol * 219Symtab::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 232Symbol * 233Symtab::SymbolAtIndex(size_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 243const Symbol * 244Symtab::SymbolAtIndex(size_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//---------------------------------------------------------------------- 256void 257Symtab::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 335void 336Symtab::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 373uint32_t 374Symtab::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 391uint32_t 392Symtab::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 409uint32_t 410Symtab::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 431uint32_t 432Symtab::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 440struct SymbolSortInfo 441{ 442 const bool sort_by_load_addr; 443 const Symbol *symbols; 444}; 445 446namespace { 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 496void 497Symtab::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 521uint32_t 522Symtab::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 538uint32_t 539Symtab::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 564uint32_t 565Symtab::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 583uint32_t 584Symtab::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 603uint32_t 604Symtab::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 627uint32_t 628Symtab::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 654Symbol * 655Symtab::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 (size_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 674size_t 675Symtab::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 694size_t 695Symtab::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 714size_t 715Symtab::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 723Symbol * 724Symtab::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 752typedef 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 761static int 762SymbolWithFileAddress (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 787static int 788SymbolWithClosestFileAddress (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 816static SymbolSearchInfo 817FindIndexPtrForSymbolContainingAddress(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 829void 830Symtab::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 857size_t 858Symtab::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 918Symbol * 919Symtab::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 939Symbol * 940Symtab::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 977Symbol * 978Symtab::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 988void 989Symtab::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 1009size_t 1010Symtab::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