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