Symtab.cpp revision a1e14750737ce399beb491973e8f9a349c3e3a1c
1//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include <map> 11 12#include "lldb/Core/Module.h" 13#include "lldb/Core/RegularExpression.h" 14#include "lldb/Core/Timer.h" 15#include "lldb/Symbol/ObjectFile.h" 16#include "lldb/Symbol/Symtab.h" 17 18using namespace lldb; 19using namespace lldb_private; 20 21 22 23Symtab::Symtab(ObjectFile *objfile) : 24 m_objfile(objfile), 25 m_symbols(), 26 m_addr_indexes(), 27 m_name_to_index() 28{ 29} 30 31Symtab::~Symtab() 32{ 33} 34 35void 36Symtab::Reserve(uint32_t count) 37{ 38 m_symbols.reserve (count); 39} 40 41Symbol * 42Symtab::Resize(uint32_t count) 43{ 44 m_symbols.resize (count); 45 return &m_symbols[0]; 46} 47 48uint32_t 49Symtab::AddSymbol(const Symbol& symbol) 50{ 51 uint32_t symbol_idx = m_symbols.size(); 52 m_name_to_index.Clear(); 53 m_addr_indexes.clear(); 54 m_symbols.push_back(symbol); 55 return symbol_idx; 56} 57 58size_t 59Symtab::GetNumSymbols() const 60{ 61 return m_symbols.size(); 62} 63 64void 65Symtab::Dump(Stream *s, Process *process) const 66{ 67 const_iterator pos; 68 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 69 s->Indent(); 70 const FileSpec &file_spec = m_objfile->GetFileSpec(); 71 const char * object_name = NULL; 72 if (m_objfile->GetModule()) 73 object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 74 75 if (file_spec) 76 s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u:\n", 77 file_spec.GetDirectory().AsCString(), 78 file_spec.GetFilename().AsCString(), 79 object_name ? "(" : "", 80 object_name ? object_name : "", 81 object_name ? ")" : "", 82 m_symbols.size()); 83 else 84 s->Printf("Symtab, num_symbols = %u:\n", m_symbols.size()); 85 s->IndentMore(); 86 87 if (!m_symbols.empty()) 88 { 89 const_iterator begin = m_symbols.begin(); 90 const_iterator end = m_symbols.end(); 91 DumpSymbolHeader (s); 92 for (pos = m_symbols.begin(); pos != end; ++pos) 93 { 94 s->Indent(); 95 pos->Dump(s, process, std::distance(begin, pos)); 96 } 97 } 98 s->IndentLess (); 99} 100 101void 102Symtab::Dump(Stream *s, Process *process, std::vector<uint32_t>& indexes) const 103{ 104 const size_t num_symbols = GetNumSymbols(); 105 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 106 s->Indent(); 107 s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size()); 108 s->IndentMore(); 109 110 if (!indexes.empty()) 111 { 112 std::vector<uint32_t>::const_iterator pos; 113 std::vector<uint32_t>::const_iterator end = indexes.end(); 114 DumpSymbolHeader (s); 115 for (pos = indexes.begin(); pos != end; ++pos) 116 { 117 uint32_t idx = *pos; 118 if (idx < num_symbols) 119 { 120 s->Indent(); 121 m_symbols[idx].Dump(s, process, idx); 122 } 123 } 124 } 125 s->IndentLess (); 126} 127 128void 129Symtab::DumpSymbolHeader (Stream *s) 130{ 131 s->Indent(" Debug symbol\n"); 132 s->Indent(" |Synthetic symbol\n"); 133 s->Indent(" ||Externally Visible\n"); 134 s->Indent(" |||\n"); 135 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n"); 136 s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n"); 137} 138 139Symbol * 140Symtab::SymbolAtIndex(uint32_t idx) 141{ 142 if (idx < m_symbols.size()) 143 return &m_symbols[idx]; 144 return NULL; 145} 146 147 148const Symbol * 149Symtab::SymbolAtIndex(uint32_t idx) const 150{ 151 if (idx < m_symbols.size()) 152 return &m_symbols[idx]; 153 return NULL; 154} 155 156//---------------------------------------------------------------------- 157// InitNameIndexes 158//---------------------------------------------------------------------- 159void 160Symtab::InitNameIndexes() 161{ 162 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 163 // Create the name index vector to be able to quickly search by name 164 const size_t count = m_symbols.size(); 165 assert(m_objfile != NULL); 166 assert(m_objfile->GetModule() != NULL); 167 m_name_to_index.Reserve (count); 168 169 UniqueCStringMap<uint32_t>::Entry entry; 170 171 for (entry.value = 0; entry.value < count; ++entry.value) 172 { 173 const Symbol *symbol = &m_symbols[entry.value]; 174 175 // Don't let trampolines get into the lookup by name map 176 // If we ever need the trampoline symbols to be searchable by name 177 // we can remove this and then possibly add a new bool to any of the 178 // Symtab functions that lookup symbols by name to indicate if they 179 // want trampolines. 180 if (symbol->IsTrampoline()) 181 continue; 182 183 const Mangled &mangled = symbol->GetMangled(); 184 entry.cstring = mangled.GetMangledName().GetCString(); 185 if (entry.cstring && entry.cstring[0]) 186 m_name_to_index.Append (entry); 187 188 entry.cstring = mangled.GetDemangledName().GetCString(); 189 if (entry.cstring && entry.cstring[0]) 190 m_name_to_index.Append (entry); 191 } 192 m_name_to_index.Sort(); 193} 194 195uint32_t 196Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 197{ 198 uint32_t prev_size = indexes.size(); 199 200 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 201 202 for (uint32_t i = start_idx; i < count; ++i) 203 { 204 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 205 indexes.push_back(i); 206 } 207 208 return indexes.size() - prev_size; 209} 210 211struct SymbolSortInfo 212{ 213 const bool sort_by_load_addr; 214 const Symbol *symbols; 215}; 216 217namespace { 218 struct SymbolIndexComparator { 219 const std::vector<Symbol>& symbols; 220 SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { } 221 bool operator()(uint32_t index_a, uint32_t index_b) { 222 addr_t value_a; 223 addr_t value_b; 224 if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) { 225 value_a = symbols[index_a].GetValue ().GetOffset(); 226 value_b = symbols[index_b].GetValue ().GetOffset(); 227 } else { 228 value_a = symbols[index_a].GetValue ().GetFileAddress(); 229 value_b = symbols[index_b].GetValue ().GetFileAddress(); 230 } 231 232 if (value_a == value_b) { 233 // The if the values are equal, use the original symbol user ID 234 lldb::user_id_t uid_a = symbols[index_a].GetID(); 235 lldb::user_id_t uid_b = symbols[index_b].GetID(); 236 if (uid_a < uid_b) 237 return true; 238 if (uid_a > uid_b) 239 return false; 240 return false; 241 } else if (value_a < value_b) 242 return true; 243 244 return false; 245 } 246 }; 247} 248 249void 250Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const 251{ 252 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__); 253 // No need to sort if we have zero or one items... 254 if (indexes.size() <= 1) 255 return; 256 257 // Sort the indexes in place using std::stable_sort. 258 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance, 259 // not correctness. The indexes vector tends to be "close" to sorted, which the 260 // stable sort handles better. 261 std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols)); 262 263 // Remove any duplicates if requested 264 if (remove_duplicates) 265 std::unique(indexes.begin(), indexes.end()); 266} 267 268uint32_t 269Symtab::AppendSymbolIndexesWithName(const ConstString& symbol_name, std::vector<uint32_t>& indexes) 270{ 271 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 272 if (symbol_name) 273 { 274 const size_t old_size = indexes.size(); 275 if (m_name_to_index.IsEmpty()) 276 InitNameIndexes(); 277 278 const char *symbol_cstr = symbol_name.GetCString(); 279 const UniqueCStringMap<uint32_t>::Entry *entry_ptr; 280 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr); 281 entry_ptr!= NULL; 282 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr)) 283 { 284 indexes.push_back (entry_ptr->value); 285 } 286 return indexes.size() - old_size; 287 } 288 return 0; 289} 290 291uint32_t 292Symtab::AppendSymbolIndexesWithNameAndType(const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) 293{ 294 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) 295 { 296 std::vector<uint32_t>::iterator pos = indexes.begin(); 297 while (pos != indexes.end()) 298 { 299 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 300 ++pos; 301 else 302 indexes.erase(pos); 303 } 304 } 305 return indexes.size(); 306} 307 308uint32_t 309Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) 310{ 311 uint32_t prev_size = indexes.size(); 312 uint32_t sym_end = m_symbols.size(); 313 314 for (int i = 0; i < sym_end; i++) 315 { 316 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 317 { 318 const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 319 if (name) 320 { 321 if (regexp.Execute (name)) 322 indexes.push_back(i); 323 } 324 } 325 } 326 return indexes.size() - prev_size; 327 328} 329 330Symbol * 331Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx) 332{ 333 const size_t count = m_symbols.size(); 334 for (uint32_t idx = start_idx; idx < count; ++idx) 335 { 336 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) 337 { 338 start_idx = idx; 339 return &m_symbols[idx]; 340 } 341 } 342 return NULL; 343} 344 345const Symbol * 346Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx) const 347{ 348 const size_t count = m_symbols.size(); 349 for (uint32_t idx = start_idx; idx < count; ++idx) 350 { 351 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) 352 { 353 start_idx = idx; 354 return &m_symbols[idx]; 355 } 356 } 357 return NULL; 358} 359 360size_t 361Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) 362{ 363 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 364 // Initialize all of the lookup by name indexes before converting NAME 365 // to a uniqued string NAME_STR below. 366 if (m_name_to_index.IsEmpty()) 367 InitNameIndexes(); 368 369 if (name) 370 { 371 // The string table did have a string that matched, but we need 372 // to check the symbols and match the symbol_type if any was given. 373 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); 374 } 375 return symbol_indexes.size(); 376} 377 378size_t 379Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) 380{ 381 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_indexes); 382 return symbol_indexes.size(); 383} 384 385Symbol * 386Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) 387{ 388 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 389 if (m_name_to_index.IsEmpty()) 390 InitNameIndexes(); 391 392 if (name) 393 { 394 std::vector<uint32_t> matching_indexes; 395 // The string table did have a string that matched, but we need 396 // to check the symbols and match the symbol_type if any was given. 397 if (AppendSymbolIndexesWithNameAndType(name, symbol_type, matching_indexes)) 398 { 399 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 400 for (pos = matching_indexes.begin(); pos != end; ++pos) 401 { 402 Symbol *symbol = SymbolAtIndex(*pos); 403 404 if (symbol->Compare(name, symbol_type)) 405 return symbol; 406 } 407 } 408 } 409 return NULL; 410} 411 412typedef struct 413{ 414 const Symtab *symtab; 415 const addr_t file_addr; 416 Symbol *match_symbol; 417 const uint32_t *match_index_ptr; 418 addr_t match_offset; 419} SymbolSearchInfo; 420 421static int 422SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 423{ 424 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 425 if (curr_symbol == NULL) 426 return -1; 427 428 const addr_t info_file_addr = info->file_addr; 429 430 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address 431 // range if the symbol has a section! 432 const AddressRange *curr_range = curr_symbol->GetAddressRangePtr(); 433 if (curr_range) 434 { 435 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 436 if (info_file_addr < curr_file_addr) 437 return -1; 438 if (info_file_addr > curr_file_addr) 439 return +1; 440 info->match_symbol = const_cast<Symbol *>(curr_symbol); 441 info->match_index_ptr = index_ptr; 442 return 0; 443 } 444 445 return -1; 446} 447 448static int 449SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 450{ 451 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 452 if (symbol == NULL) 453 return -1; 454 455 const addr_t info_file_addr = info->file_addr; 456 const AddressRange *curr_range = symbol->GetAddressRangePtr(); 457 if (curr_range) 458 { 459 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress(); 460 if (info_file_addr < curr_file_addr) 461 return -1; 462 463 // Since we are finding the closest symbol that is greater than or equal 464 // to 'info->file_addr' we set the symbol here. This will get set 465 // multiple times, but after the search is done it will contain the best 466 // symbol match 467 info->match_symbol = const_cast<Symbol *>(symbol); 468 info->match_index_ptr = index_ptr; 469 info->match_offset = info_file_addr - curr_file_addr; 470 471 if (info_file_addr > curr_file_addr) 472 return +1; 473 return 0; 474 } 475 return -1; 476} 477 478static SymbolSearchInfo 479FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 480{ 481 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 }; 482 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 483 return info; 484} 485 486 487void 488Symtab::InitAddressIndexes() 489{ 490 if (m_addr_indexes.empty()) 491 { 492 AppendSymbolIndexesWithType (eSymbolTypeFunction, m_addr_indexes); 493 AppendSymbolIndexesWithType (eSymbolTypeGlobal, m_addr_indexes); 494 AppendSymbolIndexesWithType (eSymbolTypeStatic, m_addr_indexes); 495 AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes); 496 AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes); 497 AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes); 498 SortSymbolIndexesByValue(m_addr_indexes, true); 499 m_addr_indexes.push_back(UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol 500 } 501} 502 503size_t 504Symtab::CalculateSymbolSize (Symbol *symbol) 505{ 506 // Make sure this symbol is from this symbol table... 507 if (symbol < m_symbols.data() && symbol >= m_symbols.data() + m_symbols.size()) 508 return 0; 509 510 // See if this symbol already has a byte size? 511 size_t byte_size = symbol->GetByteSize(); 512 513 if (byte_size) 514 { 515 // It does, just return it 516 return byte_size; 517 } 518 519 // Else if this is an address based symbol, figure out the delta between 520 // it and the next address based symbol 521 if (symbol->GetAddressRangePtr()) 522 { 523 if (m_addr_indexes.empty()) 524 InitAddressIndexes(); 525 const size_t num_addr_indexes = m_addr_indexes.size(); 526 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), m_addr_indexes.data(), num_addr_indexes); 527 if (info.match_index_ptr != NULL) 528 { 529 const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 530 // We can figure out the address range of all symbols except the 531 // last one by taking the delta between the current symbol and 532 // the next symbol 533 534 for (uint32_t addr_index = info.match_index_ptr - m_addr_indexes.data() + 1; 535 addr_index < num_addr_indexes; 536 ++addr_index) 537 { 538 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]); 539 if (next_symbol == NULL) 540 break; 541 542 assert (next_symbol->GetAddressRangePtr()); 543 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(); 544 if (next_file_addr > curr_file_addr) 545 { 546 byte_size = next_file_addr - curr_file_addr; 547 symbol->GetAddressRangePtr()->SetByteSize(byte_size); 548 symbol->SetSizeIsSynthesized(true); 549 break; 550 } 551 } 552 } 553 } 554 return byte_size; 555} 556 557Symbol * 558Symtab::FindSymbolWithFileAddress (addr_t file_addr) 559{ 560 if (m_addr_indexes.empty()) 561 InitAddressIndexes(); 562 563 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 564 565 uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress); 566 if (match) 567 return SymbolAtIndex (*match); 568 return NULL; 569} 570 571 572Symbol * 573Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 574{ 575 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 576 577 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress); 578 579 if (info.match_symbol) 580 { 581 if (info.match_offset < CalculateSymbolSize(info.match_symbol)) 582 return info.match_symbol; 583 } 584 return NULL; 585} 586 587Symbol * 588Symtab::FindSymbolContainingFileAddress (addr_t file_addr) 589{ 590 if (m_addr_indexes.empty()) 591 InitAddressIndexes(); 592 593 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size()); 594} 595 596