1 //===-- DWARFCompileUnit.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 "DWARFCompileUnit.h" 11 12 #include "lldb/Core/Mangled.h" 13 #include "lldb/Core/Stream.h" 14 #include "lldb/Core/Timer.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Target/ObjCLanguageRuntime.h" 17 18 #include "DWARFDebugAbbrev.h" 19 #include "DWARFDebugAranges.h" 20 #include "DWARFDebugInfo.h" 21 #include "DWARFDIECollection.h" 22 #include "DWARFFormValue.h" 23 #include "LogChannelDWARF.h" 24 #include "NameToDIE.h" 25 #include "SymbolFileDWARF.h" 26 27 using namespace lldb_private; 28 using namespace std; 29 30 extern int g_verbose; 31 32 DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : 33 m_dwarf2Data (dwarf2Data), 34 m_abbrevs (NULL), 35 m_user_data (NULL), 36 m_die_array (), 37 m_func_aranges_ap (), 38 m_base_addr (0), 39 m_offset (DW_INVALID_OFFSET), 40 m_length (0), 41 m_version (0), 42 m_addr_size (DWARFCompileUnit::GetDefaultAddressSize()) 43 { 44 } 45 46 void 47 DWARFCompileUnit::Clear() 48 { 49 m_offset = DW_INVALID_OFFSET; 50 m_length = 0; 51 m_version = 0; 52 m_abbrevs = NULL; 53 m_addr_size = DWARFCompileUnit::GetDefaultAddressSize(); 54 m_base_addr = 0; 55 m_die_array.clear(); 56 m_func_aranges_ap.reset(); 57 m_user_data = NULL; 58 } 59 60 bool 61 DWARFCompileUnit::Extract(const DataExtractor &debug_info, uint32_t* offset_ptr) 62 { 63 Clear(); 64 65 m_offset = *offset_ptr; 66 67 if (debug_info.ValidOffset(*offset_ptr)) 68 { 69 dw_offset_t abbr_offset; 70 const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); 71 m_length = debug_info.GetU32(offset_ptr); 72 m_version = debug_info.GetU16(offset_ptr); 73 abbr_offset = debug_info.GetU32(offset_ptr); 74 m_addr_size = debug_info.GetU8 (offset_ptr); 75 76 bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 77 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 78 bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); 79 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 80 81 if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) 82 { 83 m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); 84 return true; 85 } 86 87 // reset the offset to where we tried to parse from if anything went wrong 88 *offset_ptr = m_offset; 89 } 90 91 return false; 92 } 93 94 95 dw_offset_t 96 DWARFCompileUnit::Extract(dw_offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs) 97 { 98 Clear(); 99 100 m_offset = offset; 101 102 if (debug_info_data.ValidOffset(offset)) 103 { 104 m_length = debug_info_data.GetU32(&offset); 105 m_version = debug_info_data.GetU16(&offset); 106 bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset(); 107 m_abbrevs = abbrevs; 108 m_addr_size = debug_info_data.GetU8 (&offset); 109 110 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 111 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 112 113 if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset)) 114 return offset; 115 } 116 return DW_INVALID_OFFSET; 117 } 118 119 void 120 DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) 121 { 122 if (m_die_array.size() > 1) 123 { 124 // std::vectors never get any smaller when resized to a smaller size, 125 // or when clear() or erase() are called, the size will report that it 126 // is smaller, but the memory allocated remains intact (call capacity() 127 // to see this). So we need to create a temporary vector and swap the 128 // contents which will cause just the internal pointers to be swapped 129 // so that when "tmp_array" goes out of scope, it will destroy the 130 // contents. 131 132 // Save at least the compile unit DIE 133 DWARFDebugInfoEntry::collection tmp_array; 134 m_die_array.swap(tmp_array); 135 if (keep_compile_unit_die) 136 m_die_array.push_back(tmp_array.front()); 137 } 138 } 139 140 //---------------------------------------------------------------------- 141 // ParseCompileUnitDIEsIfNeeded 142 // 143 // Parses a compile unit and indexes its DIEs if it hasn't already been 144 // done. 145 //---------------------------------------------------------------------- 146 size_t 147 DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) 148 { 149 const size_t initial_die_array_size = m_die_array.size(); 150 if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) 151 return 0; // Already parsed 152 153 Timer scoped_timer (__PRETTY_FUNCTION__, 154 "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", 155 m_offset, 156 cu_die_only); 157 158 // Set the offset to that of the first DIE and calculate the start of the 159 // next compilation unit header. 160 uint32_t offset = GetFirstDIEOffset(); 161 uint32_t next_cu_offset = GetNextCompileUnitOffset(); 162 163 DWARFDebugInfoEntry die; 164 // Keep a flat array of the DIE for binary lookup by DIE offset 165 // Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); 166 // if (log) 167 // log->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x", 168 // cu->GetOffset(), 169 // cu->GetLength(), 170 // cu->GetVersion(), 171 // cu->GetAbbrevOffset(), 172 // cu->GetAddressByteSize()); 173 174 uint32_t depth = 0; 175 // We are in our compile unit, parse starting at the offset 176 // we were told to parse 177 const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data(); 178 179 const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 180 while (offset < next_cu_offset && 181 die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) 182 { 183 // if (log) 184 // log->Printf("0x%8.8x: %*.*s%s%s", 185 // die.GetOffset(), 186 // depth * 2, depth * 2, "", 187 // DW_TAG_value_to_name (die.Tag()), 188 // die.HasChildren() ? " *" : ""); 189 190 if (depth == 0) 191 { 192 uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 193 if (base_addr == LLDB_INVALID_ADDRESS) 194 base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); 195 SetBaseAddress (base_addr); 196 } 197 198 if (cu_die_only) 199 { 200 AddDIE (die); 201 return 1; 202 } 203 else if (depth == 0 && initial_die_array_size == 1) 204 { 205 // Don't append the CU die as we already did that 206 } 207 else 208 { 209 AddDIE (die); 210 } 211 212 const DWARFAbbreviationDeclaration* abbrDecl = die.GetAbbreviationDeclarationPtr(); 213 if (abbrDecl) 214 { 215 // Normal DIE 216 if (abbrDecl->HasChildren()) 217 ++depth; 218 } 219 else 220 { 221 // NULL DIE. 222 if (depth > 0) 223 --depth; 224 if (depth == 0) 225 break; // We are done with this compile unit! 226 } 227 228 } 229 230 // Give a little bit of info if we encounter corrupt DWARF (our offset 231 // should always terminate at or before the start of the next compilation 232 // unit header). 233 if (offset > next_cu_offset) 234 { 235 char path[PATH_MAX]; 236 ObjectFile *objfile = m_dwarf2Data->GetObjectFile(); 237 if (objfile) 238 { 239 objfile->GetFileSpec().GetPath(path, sizeof(path)); 240 } 241 fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x in '%s'\n", GetOffset(), offset, path); 242 } 243 244 SetDIERelations(); 245 return m_die_array.size(); 246 } 247 248 249 dw_offset_t 250 DWARFCompileUnit::GetAbbrevOffset() const 251 { 252 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 253 } 254 255 256 257 bool 258 DWARFCompileUnit::Verify(Stream *s) const 259 { 260 const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data(); 261 bool valid_offset = debug_info.ValidOffset(m_offset); 262 bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 263 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 264 bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset()); 265 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 266 bool verbose = s->GetVerbose(); 267 if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK) 268 { 269 if (verbose) 270 s->Printf(" 0x%8.8x: OK\n", m_offset); 271 return true; 272 } 273 else 274 { 275 s->Printf(" 0x%8.8x: ", m_offset); 276 277 m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0); 278 s->EOL(); 279 if (valid_offset) 280 { 281 if (!length_OK) 282 s->Printf(" The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length); 283 if (!version_OK) 284 s->Printf(" The 16 bit compile unit header version is not supported.\n"); 285 if (!abbr_offset_OK) 286 s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset()); 287 if (!addr_size_OK) 288 s->Printf(" The address size is unsupported: 0x%2.2x\n", m_addr_size); 289 } 290 else 291 s->Printf(" The start offset of the compile unit header in the .debug_info is invalid.\n"); 292 } 293 return false; 294 } 295 296 297 void 298 DWARFCompileUnit::Dump(Stream *s) const 299 { 300 s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at {0x%8.8x})\n", 301 m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset()); 302 } 303 304 305 static uint8_t g_default_addr_size = 4; 306 307 uint8_t 308 DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu) 309 { 310 if (cu) 311 return cu->GetAddressByteSize(); 312 return DWARFCompileUnit::GetDefaultAddressSize(); 313 } 314 315 uint8_t 316 DWARFCompileUnit::GetDefaultAddressSize() 317 { 318 return g_default_addr_size; 319 } 320 321 void 322 DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) 323 { 324 g_default_addr_size = addr_size; 325 } 326 327 void 328 DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, 329 DWARFDebugAranges* debug_aranges, 330 bool clear_dies_if_already_not_parsed) 331 { 332 // This function is usually called if there in no .debug_aranges section 333 // in order to produce a compile unit level set of address ranges that 334 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 335 // all compile units to stay loaded when they weren't needed. So we can end 336 // up parsing the DWARF and then throwing them all away to keep memory usage 337 // down. 338 const bool clear_dies = ExtractDIEsIfNeeded (false) > 1; 339 340 DIE()->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); 341 342 // Keep memory down by clearing DIEs if this generate function 343 // caused them to be parsed 344 if (clear_dies) 345 ClearDIEs (true); 346 347 } 348 349 350 const DWARFDebugAranges & 351 DWARFCompileUnit::GetFunctionAranges () 352 { 353 if (m_func_aranges_ap.get() == NULL) 354 { 355 m_func_aranges_ap.reset (new DWARFDebugAranges()); 356 Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES); 357 358 if (log) 359 log->Printf ("DWARFCompileUnit::GetFunctionAranges() for \"%s/%s\" compile unit at 0x%8.8x", 360 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetDirectory().GetCString(), 361 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetFilename().GetCString(), 362 m_offset); 363 DIE()->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); 364 const bool minimize = false; 365 const uint32_t fudge_size = 0; 366 m_func_aranges_ap->Sort(minimize, fudge_size); 367 } 368 return *m_func_aranges_ap.get(); 369 } 370 371 bool 372 DWARFCompileUnit::LookupAddress 373 ( 374 const dw_addr_t address, 375 DWARFDebugInfoEntry** function_die_handle, 376 DWARFDebugInfoEntry** block_die_handle 377 ) 378 { 379 bool success = false; 380 381 if (function_die_handle != NULL && DIE()) 382 { 383 384 const DWARFDebugAranges &func_aranges = GetFunctionAranges (); 385 386 // Re-check the aranges auto pointer contents in case it was created above 387 if (!func_aranges.IsEmpty()) 388 { 389 *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address)); 390 if (*function_die_handle != NULL) 391 { 392 success = true; 393 if (block_die_handle != NULL) 394 { 395 DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild(); 396 while (child) 397 { 398 if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle)) 399 break; 400 child = child->GetSibling(); 401 } 402 } 403 } 404 } 405 } 406 return success; 407 } 408 409 //---------------------------------------------------------------------- 410 // SetDIERelations() 411 // 412 // We read in all of the DIE entries into our flat list of DIE entries 413 // and now we need to go back through all of them and set the parent, 414 // sibling and child pointers for quick DIE navigation. 415 //---------------------------------------------------------------------- 416 void 417 DWARFCompileUnit::SetDIERelations() 418 { 419 #if 0 420 // Compute average bytes per DIE 421 // 422 // We can figure out what the average number of bytes per DIE is 423 // to help us pre-allocate the correct number of m_die_array 424 // entries so we don't end up doing a lot of memory copies as we 425 // are creating our DIE array when parsing 426 // 427 // Enable this code by changing "#if 0" above to "#if 1" and running 428 // the dsymutil or dwarfdump with a bunch of dwarf files and see what 429 // the running average ends up being in the stdout log. 430 static size_t g_total_cu_debug_info_size = 0; 431 static size_t g_total_num_dies = 0; 432 static size_t g_min_bytes_per_die = UINT32_MAX; 433 static size_t g_max_bytes_per_die = 0; 434 const size_t num_dies = m_die_array.size(); 435 const size_t cu_debug_info_size = GetDebugInfoSize(); 436 const size_t bytes_per_die = cu_debug_info_size / num_dies; 437 if (g_min_bytes_per_die > bytes_per_die) 438 g_min_bytes_per_die = bytes_per_die; 439 if (g_max_bytes_per_die < bytes_per_die) 440 g_max_bytes_per_die = bytes_per_die; 441 if (g_total_cu_debug_info_size == 0) 442 { 443 cout << " min max avg" << endl 444 << "n dies cu size bpd bpd bpd bpd" << endl 445 << "------ -------- --- === === ===" << endl; 446 } 447 g_total_cu_debug_info_size += cu_debug_info_size; 448 g_total_num_dies += num_dies; 449 const size_t avg_bytes_per_die = g_total_cu_debug_info_size / g_total_num_dies; 450 cout 451 << DECIMAL_WIDTH(6) << num_dies << ' ' 452 << DECIMAL_WIDTH(8) << cu_debug_info_size << ' ' 453 << DECIMAL_WIDTH(3) << bytes_per_die << ' ' 454 << DECIMAL_WIDTH(3) << g_min_bytes_per_die << ' ' 455 << DECIMAL_WIDTH(3) << g_max_bytes_per_die << ' ' 456 << DECIMAL_WIDTH(3) << avg_bytes_per_die 457 << endl; 458 #endif 459 if (m_die_array.empty()) 460 return; 461 DWARFDebugInfoEntry* die_array_begin = &m_die_array.front(); 462 DWARFDebugInfoEntry* die_array_end = &m_die_array.back(); 463 DWARFDebugInfoEntry* curr_die; 464 // We purposely are skipping the last element in the array in the loop below 465 // so that we can always have a valid next item 466 for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) 467 { 468 // Since our loop doesn't include the last element, we can always 469 // safely access the next die in the array. 470 DWARFDebugInfoEntry* next_die = curr_die + 1; 471 472 const DWARFAbbreviationDeclaration* curr_die_abbrev = curr_die->GetAbbreviationDeclarationPtr(); 473 474 if (curr_die_abbrev) 475 { 476 // Normal DIE 477 if (curr_die_abbrev->HasChildren()) 478 next_die->SetParent(curr_die); 479 else 480 curr_die->SetSibling(next_die); 481 } 482 else 483 { 484 // NULL DIE that terminates a sibling chain 485 DWARFDebugInfoEntry* parent = curr_die->GetParent(); 486 if (parent) 487 parent->SetSibling(next_die); 488 } 489 } 490 491 // Since we skipped the last element, we need to fix it up! 492 if (die_array_begin < die_array_end) 493 curr_die->SetParent(die_array_begin); 494 495 #if 0 496 // The code below will dump the DIE relations in case any modification 497 // is done to the above code. This dump can be used in a diff to make 498 // sure that no functionality is lost. 499 { 500 DWARFDebugInfoEntry::const_iterator pos; 501 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 502 puts("offset parent sibling child"); 503 puts("-------- -------- -------- --------"); 504 for (pos = m_die_array.begin(); pos != end; ++pos) 505 { 506 const DWARFDebugInfoEntry& die_ref = *pos; 507 const DWARFDebugInfoEntry* p = die_ref.GetParent(); 508 const DWARFDebugInfoEntry* s = die_ref.GetSibling(); 509 const DWARFDebugInfoEntry* c = die_ref.GetFirstChild(); 510 printf("%.8x: %.8x %.8x %.8x\n", die_ref.GetOffset(), 511 p ? p->GetOffset() : 0, 512 s ? s->GetOffset() : 0, 513 c ? c->GetOffset() : 0); 514 } 515 } 516 #endif 517 518 } 519 //---------------------------------------------------------------------- 520 // Compare function DWARFDebugAranges::Range structures 521 //---------------------------------------------------------------------- 522 static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 523 { 524 return die1.GetOffset() < die2.GetOffset(); 525 } 526 527 //---------------------------------------------------------------------- 528 // GetDIEPtr() 529 // 530 // Get the DIE (Debug Information Entry) with the specified offset. 531 //---------------------------------------------------------------------- 532 DWARFDebugInfoEntry* 533 DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset) 534 { 535 if (die_offset != DW_INVALID_OFFSET) 536 { 537 ExtractDIEsIfNeeded (false); 538 DWARFDebugInfoEntry compare_die; 539 compare_die.SetOffset(die_offset); 540 DWARFDebugInfoEntry::iterator end = m_die_array.end(); 541 DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 542 if (pos != end) 543 { 544 if (die_offset == (*pos).GetOffset()) 545 return &(*pos); 546 } 547 } 548 return NULL; // Not found in any compile units 549 } 550 551 //---------------------------------------------------------------------- 552 // GetDIEPtrContainingOffset() 553 // 554 // Get the DIE (Debug Information Entry) that contains the specified 555 // .debug_info offset. 556 //---------------------------------------------------------------------- 557 const DWARFDebugInfoEntry* 558 DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset) 559 { 560 if (die_offset != DW_INVALID_OFFSET) 561 { 562 ExtractDIEsIfNeeded (false); 563 DWARFDebugInfoEntry compare_die; 564 compare_die.SetOffset(die_offset); 565 DWARFDebugInfoEntry::iterator end = m_die_array.end(); 566 DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 567 if (pos != end) 568 { 569 if (die_offset >= (*pos).GetOffset()) 570 { 571 DWARFDebugInfoEntry::iterator next = pos + 1; 572 if (next != end) 573 { 574 if (die_offset < (*next).GetOffset()) 575 return &(*pos); 576 } 577 } 578 } 579 } 580 return NULL; // Not found in any compile units 581 } 582 583 584 585 size_t 586 DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const 587 { 588 size_t old_size = dies.Size(); 589 DWARFDebugInfoEntry::const_iterator pos; 590 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 591 for (pos = m_die_array.begin(); pos != end; ++pos) 592 { 593 if (pos->Tag() == tag) 594 dies.Append (&(*pos)); 595 } 596 597 // Return the number of DIEs added to the collection 598 return dies.Size() - old_size; 599 } 600 601 //void 602 //DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx) 603 //{ 604 // m_global_die_indexes.push_back (die_idx); 605 //} 606 // 607 // 608 //void 609 //DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die) 610 //{ 611 // // Indexes to all file level global and static variables 612 // m_global_die_indexes; 613 // 614 // if (m_die_array.empty()) 615 // return; 616 // 617 // const DWARFDebugInfoEntry* first_die = &m_die_array[0]; 618 // const DWARFDebugInfoEntry* end = first_die + m_die_array.size(); 619 // if (first_die <= die && die < end) 620 // m_global_die_indexes.push_back (die - first_die); 621 //} 622 623 624 void 625 DWARFCompileUnit::Index (const uint32_t cu_idx, 626 NameToDIE& func_basenames, 627 NameToDIE& func_fullnames, 628 NameToDIE& func_methods, 629 NameToDIE& func_selectors, 630 NameToDIE& objc_class_selectors, 631 NameToDIE& globals, 632 NameToDIE& types, 633 NameToDIE& namespaces) 634 { 635 const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); 636 637 const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 638 639 DWARFDebugInfoEntry::const_iterator pos; 640 DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); 641 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 642 for (pos = begin; pos != end; ++pos) 643 { 644 const DWARFDebugInfoEntry &die = *pos; 645 646 const dw_tag_t tag = die.Tag(); 647 648 switch (tag) 649 { 650 case DW_TAG_subprogram: 651 case DW_TAG_inlined_subroutine: 652 case DW_TAG_base_type: 653 case DW_TAG_class_type: 654 case DW_TAG_constant: 655 case DW_TAG_enumeration_type: 656 case DW_TAG_string_type: 657 case DW_TAG_subroutine_type: 658 case DW_TAG_structure_type: 659 case DW_TAG_union_type: 660 case DW_TAG_typedef: 661 case DW_TAG_namespace: 662 case DW_TAG_variable: 663 break; 664 665 default: 666 continue; 667 } 668 669 DWARFDebugInfoEntry::Attributes attributes; 670 const char *name = NULL; 671 const char *mangled_cstr = NULL; 672 bool is_variable = false; 673 bool is_declaration = false; 674 bool is_artificial = false; 675 bool has_address = false; 676 bool has_location = false; 677 bool is_global_or_static_variable = false; 678 679 dw_offset_t specification_die_offset = DW_INVALID_OFFSET; 680 const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); 681 if (num_attributes > 0) 682 { 683 is_variable = tag == DW_TAG_variable; 684 685 for (uint32_t i=0; i<num_attributes; ++i) 686 { 687 dw_attr_t attr = attributes.AttributeAtIndex(i); 688 DWARFFormValue form_value; 689 switch (attr) 690 { 691 case DW_AT_name: 692 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 693 name = form_value.AsCString(debug_str); 694 break; 695 696 case DW_AT_declaration: 697 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 698 is_declaration = form_value.Unsigned() != 0; 699 break; 700 701 case DW_AT_artificial: 702 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 703 is_artificial = form_value.Unsigned() != 0; 704 break; 705 706 case DW_AT_MIPS_linkage_name: 707 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 708 mangled_cstr = form_value.AsCString(debug_str); 709 break; 710 711 case DW_AT_low_pc: 712 case DW_AT_high_pc: 713 case DW_AT_ranges: 714 has_address = true; 715 break; 716 717 case DW_AT_entry_pc: 718 has_address = true; 719 break; 720 721 case DW_AT_location: 722 has_location = true; 723 if (tag == DW_TAG_variable) 724 { 725 const DWARFDebugInfoEntry* parent_die = die.GetParent(); 726 while ( parent_die != NULL ) 727 { 728 switch (parent_die->Tag()) 729 { 730 case DW_TAG_subprogram: 731 case DW_TAG_lexical_block: 732 case DW_TAG_inlined_subroutine: 733 // Even if this is a function level static, we don't add it. We could theoretically 734 // add these if we wanted to by introspecting into the DW_AT_location and seeing 735 // if the location describes a hard coded address, but we dont want the performance 736 // penalty of that right now. 737 is_global_or_static_variable = false; 738 // if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) 739 // { 740 // // If we have valid block data, then we have location expression bytes 741 // // that are fixed (not a location list). 742 // const uint8_t *block_data = form_value.BlockData(); 743 // if (block_data) 744 // { 745 // uint32_t block_length = form_value.Unsigned(); 746 // if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) 747 // { 748 // if (block_data[0] == DW_OP_addr) 749 // add_die = true; 750 // } 751 // } 752 // } 753 parent_die = NULL; // Terminate the while loop. 754 break; 755 756 case DW_TAG_compile_unit: 757 is_global_or_static_variable = true; 758 parent_die = NULL; // Terminate the while loop. 759 break; 760 761 default: 762 parent_die = parent_die->GetParent(); // Keep going in the while loop. 763 break; 764 } 765 } 766 } 767 break; 768 769 case DW_AT_specification: 770 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 771 specification_die_offset = form_value.Reference(this); 772 break; 773 } 774 } 775 } 776 777 switch (tag) 778 { 779 case DW_TAG_subprogram: 780 if (has_address) 781 { 782 if (name) 783 { 784 // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the 785 // simple inlined check outside the call. 786 if (ObjCLanguageRuntime::IsPossibleObjCMethodName(name)) 787 { 788 ConstString objc_class_name; 789 ConstString objc_method_name; 790 ConstString objc_base_name; 791 if (ObjCLanguageRuntime::ParseMethodName (name, 792 &objc_class_name, 793 &objc_method_name, 794 &objc_base_name)) 795 { 796 objc_class_selectors.Insert(objc_class_name, die.GetOffset()); 797 798 func_selectors.Insert (objc_method_name, die.GetOffset()); 799 800 if (!objc_base_name.IsEmpty()) 801 { 802 func_basenames.Insert (objc_base_name, die.GetOffset()); 803 func_fullnames.Insert (objc_base_name, die.GetOffset()); 804 } 805 } 806 } 807 // If we have a mangled name, then the DW_AT_name attribute 808 // is usually the method name without the class or any parameters 809 const DWARFDebugInfoEntry *parent = die.GetParent(); 810 bool is_method = false; 811 if (parent) 812 { 813 dw_tag_t parent_tag = parent->Tag(); 814 if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 815 { 816 is_method = true; 817 } 818 else 819 { 820 if (specification_die_offset != DW_INVALID_OFFSET) 821 { 822 const DWARFDebugInfoEntry *specification_die 823 = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); 824 if (specification_die) 825 { 826 parent = specification_die->GetParent(); 827 if (parent) 828 { 829 parent_tag = parent->Tag(); 830 831 if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 832 is_method = true; 833 } 834 } 835 } 836 } 837 } 838 839 840 if (is_method) 841 func_methods.Insert (ConstString(name), die.GetOffset()); 842 else 843 func_basenames.Insert (ConstString(name), die.GetOffset()); 844 } 845 if (mangled_cstr) 846 { 847 // Make sure our mangled name isn't the same string table entry 848 // as our name. If it starts with '_', then it is ok, else compare 849 // the string to make sure it isn't the same and we don't end up 850 // with duplicate entries 851 if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 852 { 853 Mangled mangled (mangled_cstr, true); 854 func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 855 if (mangled.GetDemangledName()) 856 func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 857 } 858 } 859 } 860 break; 861 862 case DW_TAG_inlined_subroutine: 863 if (has_address) 864 { 865 if (name) 866 func_basenames.Insert (ConstString(name), die.GetOffset()); 867 if (mangled_cstr) 868 { 869 // Make sure our mangled name isn't the same string table entry 870 // as our name. If it starts with '_', then it is ok, else compare 871 // the string to make sure it isn't the same and we don't end up 872 // with duplicate entries 873 if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 874 { 875 Mangled mangled (mangled_cstr, true); 876 func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 877 if (mangled.GetDemangledName()) 878 func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 879 } 880 } 881 } 882 break; 883 884 case DW_TAG_base_type: 885 case DW_TAG_class_type: 886 case DW_TAG_constant: 887 case DW_TAG_enumeration_type: 888 case DW_TAG_string_type: 889 case DW_TAG_subroutine_type: 890 case DW_TAG_structure_type: 891 case DW_TAG_union_type: 892 case DW_TAG_typedef: 893 if (name && is_declaration == false) 894 { 895 types.Insert (ConstString(name), die.GetOffset()); 896 } 897 break; 898 899 case DW_TAG_namespace: 900 if (name) 901 namespaces.Insert (ConstString(name), die.GetOffset()); 902 break; 903 904 case DW_TAG_variable: 905 if (name && has_location && is_global_or_static_variable) 906 { 907 globals.Insert (ConstString(name), die.GetOffset()); 908 // Be sure to include variables by their mangled and demangled 909 // names if they have any since a variable can have a basename 910 // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled 911 // mangled name "(anonymous namespace)::i"... 912 913 // Make sure our mangled name isn't the same string table entry 914 // as our name. If it starts with '_', then it is ok, else compare 915 // the string to make sure it isn't the same and we don't end up 916 // with duplicate entries 917 if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 918 { 919 Mangled mangled (mangled_cstr, true); 920 globals.Insert (mangled.GetMangledName(), die.GetOffset()); 921 if (mangled.GetDemangledName()) 922 globals.Insert (mangled.GetDemangledName(), die.GetOffset()); 923 } 924 } 925 break; 926 927 default: 928 continue; 929 } 930 } 931 } 932 933 934