Symtab.cpp revision cd151697a4b4d32d8818488b793ea44712945448
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/Symtab.h" 17 18using namespace lldb; 19using namespace lldb_private; 20 21 22 23Symtab::Symtab(ObjectFile *objfile) : 24 m_objfile (objfile), 25 m_symbols (), 26 m_addr_indexes (), 27 m_name_to_index (), 28 m_mutex (Mutex::eMutexTypeRecursive), 29 m_addr_indexes_computed (false), 30 m_name_indexes_computed (false) 31{ 32} 33 34Symtab::~Symtab() 35{ 36} 37 38void 39Symtab::Reserve(uint32_t count) 40{ 41 // Clients should grab the mutex from this symbol table and lock it manually 42 // when calling this function to avoid performance issues. 43 m_symbols.reserve (count); 44} 45 46Symbol * 47Symtab::Resize(uint32_t count) 48{ 49 // Clients should grab the mutex from this symbol table and lock it manually 50 // when calling this function to avoid performance issues. 51 m_symbols.resize (count); 52 return &m_symbols[0]; 53} 54 55uint32_t 56Symtab::AddSymbol(const Symbol& symbol) 57{ 58 // Clients should grab the mutex from this symbol table and lock it manually 59 // when calling this function to avoid performance issues. 60 uint32_t symbol_idx = m_symbols.size(); 61 m_name_to_index.Clear(); 62 m_addr_indexes.clear(); 63 m_symbols.push_back(symbol); 64 m_addr_indexes_computed = false; 65 m_name_indexes_computed = false; 66 return symbol_idx; 67} 68 69size_t 70Symtab::GetNumSymbols() const 71{ 72 Mutex::Locker locker (m_mutex); 73 return m_symbols.size(); 74} 75 76void 77Symtab::Dump (Stream *s, Target *target, lldb::SortOrder sort_order) 78{ 79 Mutex::Locker locker (m_mutex); 80 81// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 82 s->Indent(); 83 const FileSpec &file_spec = m_objfile->GetFileSpec(); 84 const char * object_name = NULL; 85 if (m_objfile->GetModule()) 86 object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 87 88 if (file_spec) 89 s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u", 90 file_spec.GetDirectory().AsCString(), 91 file_spec.GetFilename().AsCString(), 92 object_name ? "(" : "", 93 object_name ? object_name : "", 94 object_name ? ")" : "", 95 m_symbols.size()); 96 else 97 s->Printf("Symtab, num_symbols = %u", m_symbols.size()); 98 99 if (!m_symbols.empty()) 100 { 101 switch (sort_order) 102 { 103 case eSortOrderNone: 104 { 105 s->PutCString (":\n"); 106 DumpSymbolHeader (s); 107 const_iterator begin = m_symbols.begin(); 108 const_iterator end = m_symbols.end(); 109 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) 110 { 111 s->Indent(); 112 pos->Dump(s, target, std::distance(begin, pos)); 113 } 114 } 115 break; 116 117 case eSortOrderByName: 118 { 119 // Although we maintain a lookup by exact name map, the table 120 // isn't sorted by name. So we must make the ordered symbol list 121 // up ourselves. 122 s->PutCString (" (sorted by name):\n"); 123 DumpSymbolHeader (s); 124 typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol; 125 CStringToSymbol name_map; 126 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos) 127 { 128 const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString(); 129 if (name && name[0]) 130 name_map.insert (std::make_pair(name, &(*pos))); 131 } 132 133 for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos) 134 { 135 s->Indent(); 136 pos->second->Dump (s, target, pos->second - &m_symbols[0]); 137 } 138 } 139 break; 140 141 case eSortOrderByAddress: 142 s->PutCString (" (sorted by address):\n"); 143 DumpSymbolHeader (s); 144 if (!m_addr_indexes_computed) 145 InitAddressIndexes(); 146 const size_t num_symbols = GetNumSymbols(); 147 std::vector<uint32_t>::const_iterator pos; 148 std::vector<uint32_t>::const_iterator end = m_addr_indexes.end(); 149 for (pos = m_addr_indexes.begin(); pos != end; ++pos) 150 { 151 uint32_t idx = *pos; 152 if (idx < num_symbols) 153 { 154 s->Indent(); 155 m_symbols[idx].Dump(s, target, idx); 156 } 157 } 158 break; 159 } 160 } 161} 162 163void 164Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const 165{ 166 Mutex::Locker locker (m_mutex); 167 168 const size_t num_symbols = GetNumSymbols(); 169 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 170 s->Indent(); 171 s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size()); 172 s->IndentMore(); 173 174 if (!indexes.empty()) 175 { 176 std::vector<uint32_t>::const_iterator pos; 177 std::vector<uint32_t>::const_iterator end = indexes.end(); 178 DumpSymbolHeader (s); 179 for (pos = indexes.begin(); pos != end; ++pos) 180 { 181 uint32_t idx = *pos; 182 if (idx < num_symbols) 183 { 184 s->Indent(); 185 m_symbols[idx].Dump(s, target, idx); 186 } 187 } 188 } 189 s->IndentLess (); 190} 191 192void 193Symtab::DumpSymbolHeader (Stream *s) 194{ 195 s->Indent(" Debug symbol\n"); 196 s->Indent(" |Synthetic symbol\n"); 197 s->Indent(" ||Externally Visible\n"); 198 s->Indent(" |||\n"); 199 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n"); 200 s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n"); 201} 202 203 204static int 205CompareSymbolID (const void *key, const void *p) 206{ 207 const user_id_t match_uid = *(user_id_t*) key; 208 const user_id_t symbol_uid = ((Symbol *)p)->GetID(); 209 if (match_uid < symbol_uid) 210 return -1; 211 if (match_uid > symbol_uid) 212 return 1; 213 return 0; 214} 215 216Symbol * 217Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const 218{ 219 Mutex::Locker locker (m_mutex); 220 221 Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, 222 &m_symbols[0], 223 m_symbols.size(), 224 (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0], 225 CompareSymbolID); 226 return symbol; 227} 228 229 230Symbol * 231Symtab::SymbolAtIndex(uint32_t idx) 232{ 233 // Clients should grab the mutex from this symbol table and lock it manually 234 // when calling this function to avoid performance issues. 235 if (idx < m_symbols.size()) 236 return &m_symbols[idx]; 237 return NULL; 238} 239 240 241const Symbol * 242Symtab::SymbolAtIndex(uint32_t idx) const 243{ 244 // Clients should grab the mutex from this symbol table and lock it manually 245 // when calling this function to avoid performance issues. 246 if (idx < m_symbols.size()) 247 return &m_symbols[idx]; 248 return NULL; 249} 250 251//---------------------------------------------------------------------- 252// InitNameIndexes 253//---------------------------------------------------------------------- 254void 255Symtab::InitNameIndexes() 256{ 257 // Protected function, no need to lock mutex... 258 if (!m_name_indexes_computed) 259 { 260 m_name_indexes_computed = true; 261 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 262 // Create the name index vector to be able to quickly search by name 263 const size_t count = m_symbols.size(); 264 assert(m_objfile != NULL); 265 assert(m_objfile->GetModule() != NULL); 266 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 UniqueCStringMap<uint32_t>::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 m_name_to_index.Sort(); 313 } 314} 315 316uint32_t 317Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 318{ 319 Mutex::Locker locker (m_mutex); 320 321 uint32_t prev_size = indexes.size(); 322 323 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 324 325 for (uint32_t i = start_idx; i < count; ++i) 326 { 327 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 328 indexes.push_back(i); 329 } 330 331 return indexes.size() - prev_size; 332} 333 334uint32_t 335Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 336{ 337 Mutex::Locker locker (m_mutex); 338 339 uint32_t prev_size = indexes.size(); 340 341 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 342 343 for (uint32_t i = start_idx; i < count; ++i) 344 { 345 if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value) 346 indexes.push_back(i); 347 } 348 349 return indexes.size() - prev_size; 350} 351 352uint32_t 353Symtab::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 354{ 355 Mutex::Locker locker (m_mutex); 356 357 uint32_t prev_size = indexes.size(); 358 359 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 360 361 for (uint32_t i = start_idx; i < count; ++i) 362 { 363 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 364 { 365 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 366 indexes.push_back(i); 367 } 368 } 369 370 return indexes.size() - prev_size; 371} 372 373 374uint32_t 375Symtab::GetIndexForSymbol (const Symbol *symbol) const 376{ 377 const Symbol *first_symbol = &m_symbols[0]; 378 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 379 return symbol - first_symbol; 380 return UINT32_MAX; 381} 382 383struct SymbolSortInfo 384{ 385 const bool sort_by_load_addr; 386 const Symbol *symbols; 387}; 388 389namespace { 390 struct SymbolIndexComparator { 391 const std::vector<Symbol>& symbols; 392 SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { } 393 bool operator()(uint32_t index_a, uint32_t index_b) { 394 addr_t value_a; 395 addr_t value_b; 396 if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) { 397 value_a = symbols[index_a].GetValue ().GetOffset(); 398 value_b = symbols[index_b].GetValue ().GetOffset(); 399 } else { 400 value_a = symbols[index_a].GetValue ().GetFileAddress(); 401 value_b = symbols[index_b].GetValue ().GetFileAddress(); 402 } 403 404 if (value_a == value_b) { 405 // The if the values are equal, use the original symbol user ID 406 lldb::user_id_t uid_a = symbols[index_a].GetID(); 407 lldb::user_id_t uid_b = symbols[index_b].GetID(); 408 if (uid_a < uid_b) 409 return true; 410 if (uid_a > uid_b) 411 return false; 412 return false; 413 } else if (value_a < value_b) 414 return true; 415 416 return false; 417 } 418 }; 419} 420 421void 422Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const 423{ 424 Mutex::Locker locker (m_mutex); 425 426 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__); 427 // No need to sort if we have zero or one items... 428 if (indexes.size() <= 1) 429 return; 430 431 // Sort the indexes in place using std::stable_sort. 432 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance, 433 // not correctness. The indexes vector tends to be "close" to sorted, which the 434 // stable sort handles better. 435 std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols)); 436 437 // Remove any duplicates if requested 438 if (remove_duplicates) 439 std::unique(indexes.begin(), indexes.end()); 440} 441 442uint32_t 443Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes) 444{ 445 Mutex::Locker locker (m_mutex); 446 447 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 448 if (symbol_name) 449 { 450 const size_t old_size = indexes.size(); 451 if (!m_name_indexes_computed) 452 InitNameIndexes(); 453 454 const char *symbol_cstr = symbol_name.GetCString(); 455 const UniqueCStringMap<uint32_t>::Entry *entry_ptr; 456 457 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr); 458 entry_ptr!= NULL; 459 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr)) 460 { 461 indexes.push_back (entry_ptr->value); 462 } 463 return indexes.size() - old_size; 464 } 465 return 0; 466} 467 468uint32_t 469Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 470{ 471 Mutex::Locker locker (m_mutex); 472 473 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 474 if (symbol_name) 475 { 476 const size_t old_size = indexes.size(); 477 if (!m_name_indexes_computed) 478 InitNameIndexes(); 479 480 const char *symbol_cstr = symbol_name.GetCString(); 481 const UniqueCStringMap<uint32_t>::Entry *entry_ptr; 482 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr); 483 entry_ptr!= NULL; 484 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr)) 485 { 486 if (CheckSymbolAtIndex(entry_ptr->value, symbol_debug_type, symbol_visibility)) 487 indexes.push_back (entry_ptr->value); 488 } 489 return indexes.size() - old_size; 490 } 491 return 0; 492} 493 494uint32_t 495Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) 496{ 497 Mutex::Locker locker (m_mutex); 498 499 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) 500 { 501 std::vector<uint32_t>::iterator pos = indexes.begin(); 502 while (pos != indexes.end()) 503 { 504 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 505 ++pos; 506 else 507 indexes.erase(pos); 508 } 509 } 510 return indexes.size(); 511} 512 513uint32_t 514Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 515{ 516 Mutex::Locker locker (m_mutex); 517 518 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0) 519 { 520 std::vector<uint32_t>::iterator pos = indexes.begin(); 521 while (pos != indexes.end()) 522 { 523 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 524 ++pos; 525 else 526 indexes.erase(pos); 527 } 528 } 529 return indexes.size(); 530} 531 532 533uint32_t 534Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) 535{ 536 Mutex::Locker locker (m_mutex); 537 538 uint32_t prev_size = indexes.size(); 539 uint32_t sym_end = m_symbols.size(); 540 541 for (int i = 0; i < sym_end; i++) 542 { 543 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 544 { 545 const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 546 if (name) 547 { 548 if (regexp.Execute (name)) 549 indexes.push_back(i); 550 } 551 } 552 } 553 return indexes.size() - prev_size; 554 555} 556 557uint32_t 558Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 559{ 560 Mutex::Locker locker (m_mutex); 561 562 uint32_t prev_size = indexes.size(); 563 uint32_t sym_end = m_symbols.size(); 564 565 for (int i = 0; i < sym_end; i++) 566 { 567 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 568 { 569 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) 570 continue; 571 572 const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 573 if (name) 574 { 575 if (regexp.Execute (name)) 576 indexes.push_back(i); 577 } 578 } 579 } 580 return indexes.size() - prev_size; 581 582} 583 584Symbol * 585Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx) 586{ 587 Mutex::Locker locker (m_mutex); 588 589 const size_t count = m_symbols.size(); 590 for (uint32_t idx = start_idx; idx < count; ++idx) 591 { 592 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) 593 { 594 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) 595 { 596 start_idx = idx; 597 return &m_symbols[idx]; 598 } 599 } 600 } 601 return NULL; 602} 603 604size_t 605Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) 606{ 607 Mutex::Locker locker (m_mutex); 608 609 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 610 // Initialize all of the lookup by name indexes before converting NAME 611 // to a uniqued string NAME_STR below. 612 if (!m_name_indexes_computed) 613 InitNameIndexes(); 614 615 if (name) 616 { 617 // The string table did have a string that matched, but we need 618 // to check the symbols and match the symbol_type if any was given. 619 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes); 620 } 621 return symbol_indexes.size(); 622} 623 624size_t 625Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 626{ 627 Mutex::Locker locker (m_mutex); 628 629 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 630 // Initialize all of the lookup by name indexes before converting NAME 631 // to a uniqued string NAME_STR below. 632 if (!m_name_indexes_computed) 633 InitNameIndexes(); 634 635 if (name) 636 { 637 // The string table did have a string that matched, but we need 638 // to check the symbols and match the symbol_type if any was given. 639 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 640 } 641 return symbol_indexes.size(); 642} 643 644size_t 645Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 646{ 647 Mutex::Locker locker (m_mutex); 648 649 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 650 return symbol_indexes.size(); 651} 652 653Symbol * 654Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility) 655{ 656 Mutex::Locker locker (m_mutex); 657 658 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 659 if (!m_name_indexes_computed) 660 InitNameIndexes(); 661 662 if (name) 663 { 664 std::vector<uint32_t> matching_indexes; 665 // The string table did have a string that matched, but we need 666 // to check the symbols and match the symbol_type if any was given. 667 if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes)) 668 { 669 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 670 for (pos = matching_indexes.begin(); pos != end; ++pos) 671 { 672 Symbol *symbol = SymbolAtIndex(*pos); 673 674 if (symbol->Compare(name, symbol_type)) 675 return symbol; 676 } 677 } 678 } 679 return NULL; 680} 681 682typedef struct 683{ 684 const Symtab *symtab; 685 const addr_t file_addr; 686 Symbol *match_symbol; 687 const uint32_t *match_index_ptr; 688 addr_t match_offset; 689} SymbolSearchInfo; 690 691static int 692SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 693{ 694 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 695 if (curr_symbol == NULL) 696 return -1; 697 698 const addr_t info_file_addr = info->file_addr; 699 700 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address 701 // range if the symbol has a section! 702 const AddressRange *curr_range = curr_symbol->GetAddressRangePtr(); 703 if (curr_range) 704 { 705 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 706 if (info_file_addr < curr_file_addr) 707 return -1; 708 if (info_file_addr > curr_file_addr) 709 return +1; 710 info->match_symbol = const_cast<Symbol *>(curr_symbol); 711 info->match_index_ptr = index_ptr; 712 return 0; 713 } 714 715 return -1; 716} 717 718static int 719SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 720{ 721 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 722 if (symbol == NULL) 723 return -1; 724 725 const addr_t info_file_addr = info->file_addr; 726 const AddressRange *curr_range = symbol->GetAddressRangePtr(); 727 if (curr_range) 728 { 729 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 730 if (info_file_addr < curr_file_addr) 731 return -1; 732 733 // Since we are finding the closest symbol that is greater than or equal 734 // to 'info->file_addr' we set the symbol here. This will get set 735 // multiple times, but after the search is done it will contain the best 736 // symbol match 737 info->match_symbol = const_cast<Symbol *>(symbol); 738 info->match_index_ptr = index_ptr; 739 info->match_offset = info_file_addr - curr_file_addr; 740 741 if (info_file_addr > curr_file_addr) 742 return +1; 743 return 0; 744 } 745 return -1; 746} 747 748static SymbolSearchInfo 749FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 750{ 751 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 }; 752 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 753 return info; 754} 755 756 757void 758Symtab::InitAddressIndexes() 759{ 760 // Protected function, no need to lock mutex... 761 if (!m_addr_indexes_computed && !m_symbols.empty()) 762 { 763 m_addr_indexes_computed = true; 764#if 0 765 // The old was to add only code, trampoline or data symbols... 766 AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes); 767 AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes); 768 AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes); 769#else 770 // The new way adds all symbols with valid addresses that are section 771 // offset. 772 const_iterator begin = m_symbols.begin(); 773 const_iterator end = m_symbols.end(); 774 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) 775 { 776 if (pos->GetAddressRangePtr()) 777 m_addr_indexes.push_back (std::distance(begin, pos)); 778 } 779#endif 780 SortSymbolIndexesByValue (m_addr_indexes, false); 781 m_addr_indexes.push_back (UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol 782 } 783} 784 785size_t 786Symtab::CalculateSymbolSize (Symbol *symbol) 787{ 788 Mutex::Locker locker (m_mutex); 789 790 if (m_symbols.empty()) 791 return 0; 792 793 // Make sure this symbol is from this symbol table... 794 if (symbol < &m_symbols.front() || symbol > &m_symbols.back()) 795 return 0; 796 797 // See if this symbol already has a byte size? 798 size_t byte_size = symbol->GetByteSize(); 799 800 if (byte_size) 801 { 802 // It does, just return it 803 return byte_size; 804 } 805 806 // Else if this is an address based symbol, figure out the delta between 807 // it and the next address based symbol 808 if (symbol->GetAddressRangePtr()) 809 { 810 if (!m_addr_indexes_computed) 811 InitAddressIndexes(); 812 const size_t num_addr_indexes = m_addr_indexes.size(); 813 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes); 814 if (info.match_index_ptr != NULL) 815 { 816 const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 817 // We can figure out the address range of all symbols except the 818 // last one by taking the delta between the current symbol and 819 // the next symbol 820 821 for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1; 822 addr_index < num_addr_indexes; 823 ++addr_index) 824 { 825 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]); 826 if (next_symbol == NULL) 827 break; 828 829 assert (next_symbol->GetAddressRangePtr()); 830 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 831 if (next_file_addr > curr_file_addr) 832 { 833 byte_size = next_file_addr - curr_file_addr; 834 symbol->GetAddressRangePtr()->SetByteSize(byte_size); 835 symbol->SetSizeIsSynthesized(true); 836 break; 837 } 838 } 839 } 840 } 841 return byte_size; 842} 843 844Symbol * 845Symtab::FindSymbolWithFileAddress (addr_t file_addr) 846{ 847 Mutex::Locker locker (m_mutex); 848 849 if (!m_addr_indexes_computed) 850 InitAddressIndexes(); 851 852 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 853 854 uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress); 855 if (match) 856 return SymbolAtIndex (*match); 857 return NULL; 858} 859 860 861Symbol * 862Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 863{ 864 Mutex::Locker locker (m_mutex); 865 866 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 867 868 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 869 870 if (info.match_symbol) 871 { 872 if (info.match_offset == 0) 873 { 874 // We found an exact match! 875 return info.match_symbol; 876 } 877 878 const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol); 879 880 if (symbol_byte_size == 0) 881 { 882 // We weren't able to find the size of the symbol so lets just go 883 // with that match we found in our search... 884 return info.match_symbol; 885 } 886 887 // We were able to figure out a symbol size so lets make sure our 888 // offset puts "file_addr" in the symbol's address range. 889 if (info.match_offset < symbol_byte_size) 890 return info.match_symbol; 891 } 892 return NULL; 893} 894 895Symbol * 896Symtab::FindSymbolContainingFileAddress (addr_t file_addr) 897{ 898 Mutex::Locker locker (m_mutex); 899 900 if (!m_addr_indexes_computed) 901 InitAddressIndexes(); 902 903 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size()); 904} 905 906