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