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