Symtab.cpp revision 8d3802d9d6c1be4c0d37c4d269b18bcb865823e6
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::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 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) 346 { 347 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 348 indexes.push_back(i); 349 } 350 } 351 352 return indexes.size() - prev_size; 353} 354 355 356uint32_t 357Symtab::GetIndexForSymbol (const Symbol *symbol) const 358{ 359 const Symbol *first_symbol = &m_symbols[0]; 360 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 361 return symbol - first_symbol; 362 return UINT32_MAX; 363} 364 365struct SymbolSortInfo 366{ 367 const bool sort_by_load_addr; 368 const Symbol *symbols; 369}; 370 371namespace { 372 struct SymbolIndexComparator { 373 const std::vector<Symbol>& symbols; 374 SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { } 375 bool operator()(uint32_t index_a, uint32_t index_b) { 376 addr_t value_a; 377 addr_t value_b; 378 if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) { 379 value_a = symbols[index_a].GetValue ().GetOffset(); 380 value_b = symbols[index_b].GetValue ().GetOffset(); 381 } else { 382 value_a = symbols[index_a].GetValue ().GetFileAddress(); 383 value_b = symbols[index_b].GetValue ().GetFileAddress(); 384 } 385 386 if (value_a == value_b) { 387 // The if the values are equal, use the original symbol user ID 388 lldb::user_id_t uid_a = symbols[index_a].GetID(); 389 lldb::user_id_t uid_b = symbols[index_b].GetID(); 390 if (uid_a < uid_b) 391 return true; 392 if (uid_a > uid_b) 393 return false; 394 return false; 395 } else if (value_a < value_b) 396 return true; 397 398 return false; 399 } 400 }; 401} 402 403void 404Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const 405{ 406 Mutex::Locker locker (m_mutex); 407 408 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__); 409 // No need to sort if we have zero or one items... 410 if (indexes.size() <= 1) 411 return; 412 413 // Sort the indexes in place using std::stable_sort. 414 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance, 415 // not correctness. The indexes vector tends to be "close" to sorted, which the 416 // stable sort handles better. 417 std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols)); 418 419 // Remove any duplicates if requested 420 if (remove_duplicates) 421 std::unique(indexes.begin(), indexes.end()); 422} 423 424uint32_t 425Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes) 426{ 427 Mutex::Locker locker (m_mutex); 428 429 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 430 if (symbol_name) 431 { 432 const size_t old_size = indexes.size(); 433 if (!m_name_indexes_computed) 434 InitNameIndexes(); 435 436 const char *symbol_cstr = symbol_name.GetCString(); 437 const UniqueCStringMap<uint32_t>::Entry *entry_ptr; 438 439 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr); 440 entry_ptr!= NULL; 441 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr)) 442 { 443 indexes.push_back (entry_ptr->value); 444 } 445 return indexes.size() - old_size; 446 } 447 return 0; 448} 449 450uint32_t 451Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 452{ 453 Mutex::Locker locker (m_mutex); 454 455 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 456 if (symbol_name) 457 { 458 const size_t old_size = indexes.size(); 459 if (!m_name_indexes_computed) 460 InitNameIndexes(); 461 462 const char *symbol_cstr = symbol_name.GetCString(); 463 const UniqueCStringMap<uint32_t>::Entry *entry_ptr; 464 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr); 465 entry_ptr!= NULL; 466 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr)) 467 { 468 if (CheckSymbolAtIndex(entry_ptr->value, symbol_debug_type, symbol_visibility)) 469 indexes.push_back (entry_ptr->value); 470 } 471 return indexes.size() - old_size; 472 } 473 return 0; 474} 475 476uint32_t 477Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) 478{ 479 Mutex::Locker locker (m_mutex); 480 481 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) 482 { 483 std::vector<uint32_t>::iterator pos = indexes.begin(); 484 while (pos != indexes.end()) 485 { 486 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 487 ++pos; 488 else 489 indexes.erase(pos); 490 } 491 } 492 return indexes.size(); 493} 494 495uint32_t 496Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 497{ 498 Mutex::Locker locker (m_mutex); 499 500 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0) 501 { 502 std::vector<uint32_t>::iterator pos = indexes.begin(); 503 while (pos != indexes.end()) 504 { 505 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 506 ++pos; 507 else 508 indexes.erase(pos); 509 } 510 } 511 return indexes.size(); 512} 513 514 515uint32_t 516Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) 517{ 518 Mutex::Locker locker (m_mutex); 519 520 uint32_t prev_size = indexes.size(); 521 uint32_t sym_end = m_symbols.size(); 522 523 for (int i = 0; i < sym_end; i++) 524 { 525 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 526 { 527 const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 528 if (name) 529 { 530 if (regexp.Execute (name)) 531 indexes.push_back(i); 532 } 533 } 534 } 535 return indexes.size() - prev_size; 536 537} 538 539uint32_t 540Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 541{ 542 Mutex::Locker locker (m_mutex); 543 544 uint32_t prev_size = indexes.size(); 545 uint32_t sym_end = m_symbols.size(); 546 547 for (int i = 0; i < sym_end; i++) 548 { 549 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 550 { 551 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) 552 continue; 553 554 const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 555 if (name) 556 { 557 if (regexp.Execute (name)) 558 indexes.push_back(i); 559 } 560 } 561 } 562 return indexes.size() - prev_size; 563 564} 565 566Symbol * 567Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx) 568{ 569 Mutex::Locker locker (m_mutex); 570 571 const size_t count = m_symbols.size(); 572 for (uint32_t idx = start_idx; idx < count; ++idx) 573 { 574 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) 575 { 576 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) 577 { 578 start_idx = idx; 579 return &m_symbols[idx]; 580 } 581 } 582 } 583 return NULL; 584} 585 586size_t 587Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) 588{ 589 Mutex::Locker locker (m_mutex); 590 591 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 592 // Initialize all of the lookup by name indexes before converting NAME 593 // to a uniqued string NAME_STR below. 594 if (!m_name_indexes_computed) 595 InitNameIndexes(); 596 597 if (name) 598 { 599 // The string table did have a string that matched, but we need 600 // to check the symbols and match the symbol_type if any was given. 601 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes); 602 } 603 return symbol_indexes.size(); 604} 605 606size_t 607Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 608{ 609 Mutex::Locker locker (m_mutex); 610 611 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 612 // Initialize all of the lookup by name indexes before converting NAME 613 // to a uniqued string NAME_STR below. 614 if (!m_name_indexes_computed) 615 InitNameIndexes(); 616 617 if (name) 618 { 619 // The string table did have a string that matched, but we need 620 // to check the symbols and match the symbol_type if any was given. 621 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 622 } 623 return symbol_indexes.size(); 624} 625 626size_t 627Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 628{ 629 Mutex::Locker locker (m_mutex); 630 631 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 632 return symbol_indexes.size(); 633} 634 635Symbol * 636Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility) 637{ 638 Mutex::Locker locker (m_mutex); 639 640 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 641 if (!m_name_indexes_computed) 642 InitNameIndexes(); 643 644 if (name) 645 { 646 std::vector<uint32_t> matching_indexes; 647 // The string table did have a string that matched, but we need 648 // to check the symbols and match the symbol_type if any was given. 649 if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes)) 650 { 651 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 652 for (pos = matching_indexes.begin(); pos != end; ++pos) 653 { 654 Symbol *symbol = SymbolAtIndex(*pos); 655 656 if (symbol->Compare(name, symbol_type)) 657 return symbol; 658 } 659 } 660 } 661 return NULL; 662} 663 664typedef struct 665{ 666 const Symtab *symtab; 667 const addr_t file_addr; 668 Symbol *match_symbol; 669 const uint32_t *match_index_ptr; 670 addr_t match_offset; 671} SymbolSearchInfo; 672 673static int 674SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 675{ 676 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 677 if (curr_symbol == NULL) 678 return -1; 679 680 const addr_t info_file_addr = info->file_addr; 681 682 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address 683 // range if the symbol has a section! 684 const AddressRange *curr_range = curr_symbol->GetAddressRangePtr(); 685 if (curr_range) 686 { 687 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 688 if (info_file_addr < curr_file_addr) 689 return -1; 690 if (info_file_addr > curr_file_addr) 691 return +1; 692 info->match_symbol = const_cast<Symbol *>(curr_symbol); 693 info->match_index_ptr = index_ptr; 694 return 0; 695 } 696 697 return -1; 698} 699 700static int 701SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 702{ 703 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 704 if (symbol == NULL) 705 return -1; 706 707 const addr_t info_file_addr = info->file_addr; 708 const AddressRange *curr_range = symbol->GetAddressRangePtr(); 709 if (curr_range) 710 { 711 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 712 if (info_file_addr < curr_file_addr) 713 return -1; 714 715 // Since we are finding the closest symbol that is greater than or equal 716 // to 'info->file_addr' we set the symbol here. This will get set 717 // multiple times, but after the search is done it will contain the best 718 // symbol match 719 info->match_symbol = const_cast<Symbol *>(symbol); 720 info->match_index_ptr = index_ptr; 721 info->match_offset = info_file_addr - curr_file_addr; 722 723 if (info_file_addr > curr_file_addr) 724 return +1; 725 return 0; 726 } 727 return -1; 728} 729 730static SymbolSearchInfo 731FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 732{ 733 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 }; 734 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 735 return info; 736} 737 738 739void 740Symtab::InitAddressIndexes() 741{ 742 // Protected function, no need to lock mutex... 743 if (!m_addr_indexes_computed && !m_symbols.empty()) 744 { 745 m_addr_indexes_computed = true; 746#if 0 747 // The old was to add only code, trampoline or data symbols... 748 AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes); 749 AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes); 750 AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes); 751#else 752 // The new way adds all symbols with valid addresses that are section 753 // offset. 754 const_iterator begin = m_symbols.begin(); 755 const_iterator end = m_symbols.end(); 756 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) 757 { 758 if (pos->GetAddressRangePtr()) 759 m_addr_indexes.push_back (std::distance(begin, pos)); 760 } 761#endif 762 SortSymbolIndexesByValue (m_addr_indexes, false); 763 m_addr_indexes.push_back (UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol 764 } 765} 766 767size_t 768Symtab::CalculateSymbolSize (Symbol *symbol) 769{ 770 Mutex::Locker locker (m_mutex); 771 772 if (m_symbols.empty()) 773 return 0; 774 775 // Make sure this symbol is from this symbol table... 776 if (symbol < &m_symbols.front() || symbol > &m_symbols.back()) 777 return 0; 778 779 // See if this symbol already has a byte size? 780 size_t byte_size = symbol->GetByteSize(); 781 782 if (byte_size) 783 { 784 // It does, just return it 785 return byte_size; 786 } 787 788 // Else if this is an address based symbol, figure out the delta between 789 // it and the next address based symbol 790 if (symbol->GetAddressRangePtr()) 791 { 792 if (!m_addr_indexes_computed) 793 InitAddressIndexes(); 794 const size_t num_addr_indexes = m_addr_indexes.size(); 795 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes); 796 if (info.match_index_ptr != NULL) 797 { 798 const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 799 // We can figure out the address range of all symbols except the 800 // last one by taking the delta between the current symbol and 801 // the next symbol 802 803 for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1; 804 addr_index < num_addr_indexes; 805 ++addr_index) 806 { 807 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]); 808 if (next_symbol == NULL) 809 break; 810 811 assert (next_symbol->GetAddressRangePtr()); 812 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 813 if (next_file_addr > curr_file_addr) 814 { 815 byte_size = next_file_addr - curr_file_addr; 816 symbol->GetAddressRangePtr()->SetByteSize(byte_size); 817 symbol->SetSizeIsSynthesized(true); 818 break; 819 } 820 } 821 } 822 } 823 return byte_size; 824} 825 826Symbol * 827Symtab::FindSymbolWithFileAddress (addr_t file_addr) 828{ 829 Mutex::Locker locker (m_mutex); 830 831 if (!m_addr_indexes_computed) 832 InitAddressIndexes(); 833 834 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 835 836 uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress); 837 if (match) 838 return SymbolAtIndex (*match); 839 return NULL; 840} 841 842 843Symbol * 844Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 845{ 846 Mutex::Locker locker (m_mutex); 847 848 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 849 850 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 851 852 if (info.match_symbol) 853 { 854 if (info.match_offset == 0) 855 { 856 // We found an exact match! 857 return info.match_symbol; 858 } 859 860 const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol); 861 862 if (symbol_byte_size == 0) 863 { 864 // We weren't able to find the size of the symbol so lets just go 865 // with that match we found in our search... 866 return info.match_symbol; 867 } 868 869 // We were able to figure out a symbol size so lets make sure our 870 // offset puts "file_addr" in the symbol's address range. 871 if (info.match_offset < symbol_byte_size) 872 return info.match_symbol; 873 } 874 return NULL; 875} 876 877Symbol * 878Symtab::FindSymbolContainingFileAddress (addr_t file_addr) 879{ 880 Mutex::Locker locker (m_mutex); 881 882 if (!m_addr_indexes_computed) 883 InitAddressIndexes(); 884 885 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size()); 886} 887 888