DWARFDebugInfo.cpp revision 7e5fa7fc1f8efd24c078e063b2c4b5e13ba5be20
1//===-- DWARFDebugInfo.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 "SymbolFileDWARF.h" 11 12#include <algorithm> 13#include <set> 14 15#include "lldb/Core/RegularExpression.h" 16#include "lldb/Core/Stream.h" 17#include "lldb/Symbol/ObjectFile.h" 18 19#include "DWARFDebugAranges.h" 20#include "DWARFDebugInfo.h" 21#include "DWARFCompileUnit.h" 22#include "DWARFDebugAranges.h" 23#include "DWARFDebugInfoEntry.h" 24#include "DWARFFormValue.h" 25#include "LogChannelDWARF.h" 26 27using namespace lldb_private; 28using namespace std; 29 30//---------------------------------------------------------------------- 31// Constructor 32//---------------------------------------------------------------------- 33DWARFDebugInfo::DWARFDebugInfo() : 34 m_dwarf2Data(NULL), 35 m_compile_units(), 36 m_cu_aranges_ap () 37{ 38} 39 40//---------------------------------------------------------------------- 41// SetDwarfData 42//---------------------------------------------------------------------- 43void 44DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data) 45{ 46 m_dwarf2Data = dwarf2Data; 47 m_compile_units.clear(); 48} 49 50 51DWARFDebugAranges & 52DWARFDebugInfo::GetCompileUnitAranges () 53{ 54 if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) 55 { 56 Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES); 57 58 m_cu_aranges_ap.reset (new DWARFDebugAranges()); 59 const DataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data(); 60 if (debug_aranges_data.GetByteSize() > 0) 61 { 62 if (log) 63 log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s/%s\" from .debug_aranges", 64 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetDirectory().GetCString(), 65 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetFilename().GetCString()); 66 m_cu_aranges_ap->Extract (debug_aranges_data); 67 68 } 69 else 70 { 71 if (log) 72 log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s/%s\" by parsing", 73 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetDirectory().GetCString(), 74 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetFilename().GetCString()); 75 const uint32_t num_compile_units = GetNumCompileUnits(); 76 uint32_t idx; 77 const bool clear_dies_if_already_not_parsed = true; 78 for (idx = 0; idx < num_compile_units; ++idx) 79 { 80 DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx); 81 if (cu) 82 cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed); 83 } 84 } 85 86 // Sort with a fudge factor of 16 to make sure if we have a lot 87 // of functions in the compile unit whose end address if followed 88 // a start address that is "fudge_size" bytes close, it will combine 89 // the arange entries. This currently happens a lot on x86_64. This 90 // will help reduce the size of the aranges since sort will sort all 91 // of them and combine aranges that are consecutive for ranges in the 92 // same compile unit and we really don't need it to be all that 93 // accurate since we will get exact accuracy when we search the 94 // actual compile unit aranges which point to the exact range and 95 // the exact DIE offset of the function. 96 const bool minimize = true; 97 const uint32_t fudge_factor = 16; 98 m_cu_aranges_ap->Sort (minimize, fudge_factor); 99 } 100 return *m_cu_aranges_ap.get(); 101} 102 103 104//---------------------------------------------------------------------- 105// LookupAddress 106//---------------------------------------------------------------------- 107bool 108DWARFDebugInfo::LookupAddress 109( 110 const dw_addr_t address, 111 const dw_offset_t hint_die_offset, 112 DWARFCompileUnitSP& cu_sp, 113 DWARFDebugInfoEntry** function_die, 114 DWARFDebugInfoEntry** block_die 115) 116{ 117 118 if (hint_die_offset != DW_INVALID_OFFSET) 119 cu_sp = GetCompileUnit(hint_die_offset); 120 else 121 { 122 DWARFDebugAranges &cu_aranges = GetCompileUnitAranges (); 123 const dw_offset_t cu_offset = cu_aranges.FindAddress (address); 124 cu_sp = GetCompileUnit(cu_offset); 125 } 126 127 if (cu_sp.get()) 128 { 129 if (cu_sp->LookupAddress(address, function_die, block_die)) 130 return true; 131 cu_sp.reset(); 132 } 133 else 134 { 135 // The hint_die_offset may have been a pointer to the actual item that 136 // we are looking for 137 DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp); 138 if (die_ptr) 139 { 140 if (cu_sp.get()) 141 { 142 if (function_die || block_die) 143 return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die); 144 145 // We only wanted the compile unit that contained this address 146 return true; 147 } 148 } 149 } 150 return false; 151} 152 153 154void 155DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() 156{ 157 if (m_compile_units.empty()) 158 { 159 if (m_dwarf2Data != NULL) 160 { 161 uint32_t offset = 0; 162 const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data(); 163 while (debug_info_data.ValidOffset(offset)) 164 { 165 DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); 166 // Out of memory? 167 if (cu_sp.get() == NULL) 168 break; 169 170 if (cu_sp->Extract(debug_info_data, &offset) == false) 171 break; 172 173 m_compile_units.push_back(cu_sp); 174 175 offset = cu_sp->GetNextCompileUnitOffset(); 176 } 177 } 178 } 179} 180 181uint32_t 182DWARFDebugInfo::GetNumCompileUnits() 183{ 184 ParseCompileUnitHeadersIfNeeded(); 185 return m_compile_units.size(); 186} 187 188DWARFCompileUnit* 189DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) 190{ 191 DWARFCompileUnit* cu = NULL; 192 if (idx < GetNumCompileUnits()) 193 cu = m_compile_units[idx].get(); 194 return cu; 195} 196 197static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b) 198{ 199 return a->GetOffset() < b->GetOffset(); 200} 201 202 203static int 204CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem) 205{ 206 const dw_offset_t key_cu_offset = *(dw_offset_t*) key; 207 const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset(); 208 if (key_cu_offset < cu_offset) 209 return -1; 210 if (key_cu_offset > cu_offset) 211 return 1; 212 return 0; 213} 214 215DWARFCompileUnitSP 216DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) 217{ 218 DWARFCompileUnitSP cu_sp; 219 uint32_t cu_idx = DW_INVALID_INDEX; 220 if (cu_offset != DW_INVALID_OFFSET) 221 { 222 ParseCompileUnitHeadersIfNeeded(); 223 224 DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset); 225 if (match) 226 { 227 cu_sp = *match; 228 cu_idx = match - &m_compile_units[0]; 229 } 230 } 231 if (idx_ptr) 232 *idx_ptr = cu_idx; 233 return cu_sp; 234} 235 236DWARFCompileUnitSP 237DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) 238{ 239 DWARFCompileUnitSP cu_sp; 240 if (die_offset != DW_INVALID_OFFSET) 241 { 242 ParseCompileUnitHeadersIfNeeded(); 243 244 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 245 CompileUnitColl::const_iterator pos; 246 247 for (pos = m_compile_units.begin(); pos != end_pos; ++pos) 248 { 249 dw_offset_t cu_start_offset = (*pos)->GetOffset(); 250 dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset(); 251 if (cu_start_offset <= die_offset && die_offset < cu_end_offset) 252 { 253 cu_sp = *pos; 254 break; 255 } 256 } 257 } 258 return cu_sp; 259} 260 261//---------------------------------------------------------------------- 262// Compare function DWARFDebugAranges::Range structures 263//---------------------------------------------------------------------- 264static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 265{ 266 return die1.GetOffset() < die2.GetOffset(); 267} 268 269 270//---------------------------------------------------------------------- 271// GetDIE() 272// 273// Get the DIE (Debug Information Entry) with the specified offset. 274//---------------------------------------------------------------------- 275DWARFDebugInfoEntry* 276DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 277{ 278 DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 279 if (cu_sp_ptr) 280 *cu_sp_ptr = cu_sp; 281 if (cu_sp.get()) 282 return cu_sp->GetDIEPtr(die_offset); 283 return NULL; // Not found in any compile units 284} 285 286DWARFDebugInfoEntry* 287DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle) 288{ 289 assert (cu_handle); 290 DWARFDebugInfoEntry* die = NULL; 291 if (*cu_handle) 292 die = (*cu_handle)->GetDIEPtr(die_offset); 293 294 if (die == NULL) 295 { 296 DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset)); 297 if (cu_sp.get()) 298 { 299 *cu_handle = cu_sp.get(); 300 die = cu_sp->GetDIEPtr(die_offset); 301 } 302 } 303 if (die == NULL) 304 *cu_handle = NULL; 305 return die; 306} 307 308 309const DWARFDebugInfoEntry* 310DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 311{ 312 DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 313 if (cu_sp_ptr) 314 *cu_sp_ptr = cu_sp; 315 if (cu_sp.get()) 316 return cu_sp->GetDIEPtrContainingOffset(die_offset); 317 318 return NULL; // Not found in any compile units 319 320} 321 322//---------------------------------------------------------------------- 323// DWARFDebugInfo_ParseCallback 324// 325// A callback function for the static DWARFDebugInfo::Parse() function 326// that gets parses all compile units and DIE's into an internate 327// representation for further modification. 328//---------------------------------------------------------------------- 329 330static dw_offset_t 331DWARFDebugInfo_ParseCallback 332( 333 SymbolFileDWARF* dwarf2Data, 334 DWARFCompileUnitSP& cu_sp, 335 DWARFDebugInfoEntry* die, 336 const dw_offset_t next_offset, 337 const uint32_t curr_depth, 338 void* userData 339) 340{ 341 DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData; 342 DWARFCompileUnit* cu = cu_sp.get(); 343 if (die) 344 { 345 cu->AddDIE(*die); 346 } 347 else if (cu) 348 { 349 debug_info->AddCompileUnit(cu_sp); 350 } 351 352 // Just return the current offset to parse the next CU or DIE entry 353 return next_offset; 354} 355 356//---------------------------------------------------------------------- 357// AddCompileUnit 358//---------------------------------------------------------------------- 359void 360DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu) 361{ 362 m_compile_units.push_back(cu); 363} 364 365/* 366void 367DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die) 368{ 369 m_die_array.push_back(die); 370} 371*/ 372 373 374 375 376//---------------------------------------------------------------------- 377// Parse 378// 379// Parses the .debug_info section and uses the .debug_abbrev section 380// and various other sections in the SymbolFileDWARF class and calls the 381// supplied callback function each time a compile unit header, or debug 382// information entry is successfully parsed. This function can be used 383// for different tasks such as parsing the file contents into a 384// structured data, dumping, verifying and much more. 385//---------------------------------------------------------------------- 386void 387DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData) 388{ 389 if (dwarf2Data) 390 { 391 uint32_t offset = 0; 392 uint32_t depth = 0; 393 DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); 394 if (cu.get() == NULL) 395 return; 396 DWARFDebugInfoEntry die; 397 398 while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) 399 { 400 const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); 401 402 depth = 0; 403 // Call the callback function with no DIE pointer for the compile unit 404 // and get the offset that we are to continue to parse from 405 offset = callback(dwarf2Data, cu, NULL, offset, depth, userData); 406 407 // Make sure we are within our compile unit 408 if (offset < next_cu_offset) 409 { 410 // We are in our compile unit, parse starting at the offset 411 // we were told to parse 412 bool done = false; 413 while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) 414 { 415 // Call the callback function with DIE pointer that falls within the compile unit 416 offset = callback(dwarf2Data, cu, &die, offset, depth, userData); 417 418 if (die.IsNULL()) 419 { 420 if (depth) 421 --depth; 422 else 423 done = true; // We are done with this compile unit! 424 } 425 else if (die.HasChildren()) 426 ++depth; 427 } 428 } 429 430 // Make sure the offset returned is valid, and if not stop parsing. 431 // Returning DW_INVALID_OFFSET from this callback is a good way to end 432 // all parsing 433 if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) 434 break; 435 436 // See if during the callback anyone retained a copy of the compile 437 // unit other than ourselves and if so, let whomever did own the object 438 // and create a new one for our own use! 439 if (!cu.unique()) 440 cu.reset(new DWARFCompileUnit(dwarf2Data)); 441 442 443 // Make sure we start on a proper 444 offset = next_cu_offset; 445 } 446 } 447} 448 449/* 450typedef struct AddressRangeTag 451{ 452 dw_addr_t lo_pc; 453 dw_addr_t hi_pc; 454 dw_offset_t die_offset; 455} AddressRange; 456*/ 457struct DIERange 458{ 459 DIERange() : 460 range(), 461 lo_die_offset(), 462 hi_die_offset() 463 { 464 } 465 466 DWARFDebugAranges::Range range; 467 dw_offset_t lo_die_offset; 468 dw_offset_t hi_die_offset; 469}; 470 471typedef struct DwarfStat 472{ 473 DwarfStat() : count(0), byte_size(0) {} 474 uint32_t count; 475 uint32_t byte_size; 476} DwarfStat; 477 478typedef map<dw_attr_t, DwarfStat> DwarfAttrStatMap; 479 480typedef struct DIEStat 481{ 482 DIEStat() : count(0), byte_size(0), attr_stats() {} 483 uint32_t count; 484 uint32_t byte_size; 485 DwarfAttrStatMap attr_stats; 486} DIEStat; 487 488typedef map<dw_tag_t, DIEStat> DIEStatMap; 489struct VerifyInfo 490{ 491 VerifyInfo(Stream* the_strm) : 492 strm(the_strm), 493 die_ranges(), 494 addr_range_errors(0), 495 sibling_errors(0), 496 die_stats() 497 { 498 } 499 500 Stream* strm; 501 vector<DIERange> die_ranges; 502 uint32_t addr_range_errors; 503 uint32_t sibling_errors; 504 DIEStatMap die_stats; 505 506 DISALLOW_COPY_AND_ASSIGN(VerifyInfo); 507 508}; 509 510 511//---------------------------------------------------------------------- 512// VerifyCallback 513// 514// A callback function for the static DWARFDebugInfo::Parse() function 515// that gets called each time a compile unit header or debug information 516// entry is successfully parsed. 517// 518// This function will verify the DWARF information is well formed by 519// making sure that any DW_TAG_compile_unit tags that have valid address 520// ranges (DW_AT_low_pc and DW_AT_high_pc) have no gaps in the address 521// ranges of it contained DW_TAG_subprogram tags. Also the sibling chain 522// and relationships are verified to make sure nothing gets hosed up 523// when dead stripping occurs. 524//---------------------------------------------------------------------- 525 526static dw_offset_t 527VerifyCallback 528( 529 SymbolFileDWARF* dwarf2Data, 530 DWARFCompileUnitSP& cu_sp, 531 DWARFDebugInfoEntry* die, 532 const dw_offset_t next_offset, 533 const uint32_t curr_depth, 534 void* userData 535) 536{ 537 VerifyInfo* verifyInfo = (VerifyInfo*)userData; 538 539 const DWARFCompileUnit* cu = cu_sp.get(); 540 Stream *s = verifyInfo->strm; 541 bool verbose = s->GetVerbose(); 542 if (die) 543 { 544 // die->Dump(dwarf2Data, cu, f); 545 const DWARFAbbreviationDeclaration* abbrevDecl = die->GetAbbreviationDeclarationPtr(); 546 // We have a DIE entry 547 if (abbrevDecl) 548 { 549 const dw_offset_t die_offset = die->GetOffset(); 550 const dw_offset_t sibling = die->GetAttributeValueAsReference(dwarf2Data, cu, DW_AT_sibling, DW_INVALID_OFFSET); 551 552 if (sibling != DW_INVALID_OFFSET) 553 { 554 if (sibling <= next_offset) 555 { 556 if (verifyInfo->sibling_errors++ == 0) 557 s->Printf("ERROR\n"); 558 s->Printf(" 0x%8.8x: sibling attribute (0x%8.8x) in this die is not valid: it is less than this DIE or some of its contents.\n", die->GetOffset(), sibling); 559 } 560 else if (sibling > verifyInfo->die_ranges.back().hi_die_offset) 561 { 562 if (verifyInfo->sibling_errors++ == 0) 563 s->Printf("ERROR\n"); 564 s->Printf(" 0x%8.8x: sibling attribute (0x%8.8x) in this DIE is not valid: it is greater than the end of the parent scope.\n", die->GetOffset(), sibling); 565 } 566 } 567 568 if ((die_offset < verifyInfo->die_ranges.back().lo_die_offset) || (die_offset >= verifyInfo->die_ranges.back().hi_die_offset)) 569 { 570 if (verifyInfo->sibling_errors++ == 0) 571 s->Printf("ERROR\n"); 572 s->Printf(" 0x%8.8x: DIE offset is not within the parent DIE range {0x%8.8x}: (0x%8.8x - 0x%8.8x)\n", 573 die->GetOffset(), 574 verifyInfo->die_ranges.back().range.offset, 575 verifyInfo->die_ranges.back().lo_die_offset, 576 verifyInfo->die_ranges.back().hi_die_offset); 577 578 } 579 580 dw_tag_t tag = abbrevDecl->Tag(); 581 582 // Keep some stats on this DWARF file 583 verifyInfo->die_stats[tag].count++; 584 verifyInfo->die_stats[tag].byte_size += (next_offset - die->GetOffset()); 585 586 if (verbose) 587 { 588 DIEStat& tag_stat = verifyInfo->die_stats[tag]; 589 590 const DataExtractor& debug_info = dwarf2Data->get_debug_info_data(); 591 592 dw_offset_t offset = die->GetOffset(); 593 // Skip the abbreviation code so we are at the data for the attributes 594 debug_info.Skip_LEB128(&offset); 595 596 const uint32_t numAttributes = abbrevDecl->NumAttributes(); 597 dw_attr_t attr; 598 dw_form_t form; 599 for (uint32_t idx = 0; idx < numAttributes; ++idx) 600 { 601 dw_offset_t start_offset = offset; 602 abbrevDecl->GetAttrAndFormByIndexUnchecked(idx, attr, form); 603 DWARFFormValue::SkipValue(form, debug_info, &offset, cu); 604 605 if (tag_stat.attr_stats.find(attr) == tag_stat.attr_stats.end()) 606 { 607 tag_stat.attr_stats[attr].count = 0; 608 tag_stat.attr_stats[attr].byte_size = 0; 609 } 610 611 tag_stat.attr_stats[attr].count++; 612 tag_stat.attr_stats[attr].byte_size += offset - start_offset; 613 } 614 } 615 616 DWARFDebugAranges::Range range; 617 range.offset = die->GetOffset(); 618 619 switch (tag) 620 { 621 case DW_TAG_compile_unit: 622 // Check for previous subroutines that were within a previous 623 // 624 // VerifyAddressRangesForCU(verifyInfo); 625 // Remember which compile unit we are dealing with so we can verify 626 // the address ranges within it (if any) are contiguous. The DWARF 627 // spec states that if a compile unit TAG has high and low PC 628 // attributes, there must be no gaps in the address ranges of it's 629 // contained subroutines. If there are gaps, the high and low PC 630 // must not be in the DW_TAG_compile_unit's attributes. Errors like 631 // this can crop up when optimized code is dead stripped and the debug 632 // information isn't properly fixed up for output. 633 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); 634 if (range.lo_pc != DW_INVALID_ADDRESS) 635 { 636 range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); 637 if (s->GetVerbose()) 638 { 639 s->Printf("\n CU "); 640 range.Dump(s); 641 } 642 } 643 else 644 { 645 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_entry_pc, DW_INVALID_ADDRESS); 646 } 647 break; 648 649 case DW_TAG_subprogram: 650 // If the DW_TAG_compile_unit that contained this function had a 651 // valid address range, add all of the valid subroutine address 652 // ranges to a collection of addresses which will be sorted 653 // and verified right before the next DW_TAG_compile_unit is 654 // processed to make sure that there are no gaps in the address 655 // range. 656 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); 657 if (range.lo_pc != DW_INVALID_ADDRESS) 658 { 659 range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); 660 if (range.hi_pc() != DW_INVALID_ADDRESS) 661 { 662 range.offset = die->GetOffset(); 663 bool valid = range.ValidRange(); 664 if (!valid || s->GetVerbose()) 665 { 666 s->Printf("\n FUNC "); 667 range.Dump(s); 668 if (!valid) 669 { 670 ++verifyInfo->addr_range_errors; 671 s->Printf(" ERROR: Invalid address range for function."); 672 } 673 } 674 } 675 } 676 break; 677 678 case DW_TAG_lexical_block: 679 case DW_TAG_inlined_subroutine: 680 { 681 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); 682 if (range.lo_pc != DW_INVALID_ADDRESS) 683 { 684 range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); 685 if (range.hi_pc() != DW_INVALID_ADDRESS) 686 { 687 range.offset = die->GetOffset(); 688 bool valid = range.ValidRange(); 689 if (!valid || s->GetVerbose()) 690 { 691 s->Printf("\n BLCK "); 692 range.Dump(s); 693 if (!valid) 694 { 695 ++verifyInfo->addr_range_errors; 696 s->Printf(" ERROR: Invalid address range for block or inlined subroutine."); 697 } 698 } 699 } 700 } 701 } 702 break; 703 } 704 705 if (range.ValidRange() && verifyInfo->die_ranges.back().range.ValidRange()) 706 { 707 if (!verifyInfo->die_ranges.back().range.Contains(range)) 708 { 709 ++verifyInfo->addr_range_errors; 710 s->Printf("\n "); 711 range.Dump(s); 712 s->Printf(" ERROR: Range is not in parent"); 713 verifyInfo->die_ranges.back().range.Dump(s); 714 } 715 } 716 717 if (die->HasChildren()) 718 { 719 // Keep tabs on the valid address ranges for the current item to make 720 // sure that it all fits (make sure the sibling offsets got fixed up 721 // correctly if any functions were dead stripped). 722 DIERange die_range; 723 die_range.range = range; 724 die_range.lo_die_offset = next_offset; 725 die_range.hi_die_offset = sibling; 726 if (die_range.hi_die_offset == DW_INVALID_OFFSET) 727 die_range.hi_die_offset = verifyInfo->die_ranges.back().hi_die_offset; 728 verifyInfo->die_ranges.push_back(die_range); 729 } 730 } 731 else 732 { 733 // NULL entry 734 verifyInfo->die_ranges.pop_back(); 735 } 736 } 737 else 738 { 739 // cu->Dump(ostrm_ptr); // Dump the compile unit for the DIE 740 // We have a new compile unit header 741 verifyInfo->die_ranges.clear(); 742 DIERange die_range; 743 die_range.range.offset = cu->GetOffset(); 744 die_range.lo_die_offset = next_offset; 745 die_range.hi_die_offset = cu->GetNextCompileUnitOffset(); 746 verifyInfo->die_ranges.push_back(die_range); 747 } 748 749 // Just return the current offset to parse the next CU or DIE entry 750 return next_offset; 751} 752 753 754class CompareDIEStatSizes 755{ 756public: 757 bool operator() (const DIEStatMap::const_iterator& pos1, const DIEStatMap::const_iterator& pos2) const 758 { 759 return pos1->second.byte_size <= pos2->second.byte_size; 760 } 761}; 762 763class CompareAttrDIEStatSizes 764{ 765public: 766 bool operator() (const DwarfAttrStatMap::const_iterator& pos1, const DwarfAttrStatMap::const_iterator& pos2) const 767 { 768 return pos1->second.byte_size <= pos2->second.byte_size; 769 } 770}; 771 772//---------------------------------------------------------------------- 773// Verify 774// 775// Verifies the DWARF information is valid. 776//---------------------------------------------------------------------- 777void 778DWARFDebugInfo::Verify(Stream *s, SymbolFileDWARF* dwarf2Data) 779{ 780 s->Printf("Verifying Compile Unit Header chain....."); 781 VerifyInfo verifyInfo(s); 782 verifyInfo.addr_range_errors = 0; 783 verifyInfo.sibling_errors = 0; 784 785 bool verbose = s->GetVerbose(); 786 787 uint32_t offset = 0; 788 if (verbose) 789 s->EOL(); 790// vector<dw_offset_t> valid_cu_offsets; 791 DWARFCompileUnit cu (dwarf2Data); 792 bool success = true; 793 while ( success && dwarf2Data->get_debug_info_data().ValidOffset(offset+cu.Size()) ) 794 { 795 success = cu.Extract (dwarf2Data->get_debug_info_data(), &offset); 796 if (!success) 797 s->Printf("ERROR\n"); 798 // else 799 // valid_cu_offsets.push_back(cu.GetOffset()); 800 801 cu.Verify(verifyInfo.strm); 802 offset = cu.GetNextCompileUnitOffset(); 803 } 804 805 if (success) 806 s->Printf("OK\n"); 807 808 s->Printf("Verifying address ranges and siblings..."); 809 if (verbose) 810 s->EOL(); 811 DWARFDebugInfo::Parse(dwarf2Data, VerifyCallback, &verifyInfo); 812 813// VerifyAddressRangesForCU(&verifyInfo); 814 815 if (verifyInfo.addr_range_errors > 0) 816 s->Printf("\nERRORS - %u error(s) were found.\n", verifyInfo.addr_range_errors); 817 else 818 s->Printf("OK\n"); 819 820 uint32_t total_category_sizes[kNumTagCategories] = {0}; 821 uint32_t total_category_count[kNumTagCategories] = {0}; 822 uint32_t total_die_count = 0; 823 uint32_t total_die_size = 0; 824 825 typedef set<DIEStatMap::const_iterator, CompareDIEStatSizes> DIEStatBySizeMap; 826 827 s->PutCString( "\n" 828 "DWARF Statistics\n" 829 "Count Size Size % Tag\n" 830 "-------- -------- -------- -------------------------------------------\n"); 831 DIEStatBySizeMap statBySizeMap; 832 DIEStatMap::const_iterator pos; 833 DIEStatMap::const_iterator end_pos = verifyInfo.die_stats.end(); 834 for (pos = verifyInfo.die_stats.begin(); pos != end_pos; ++pos) 835 { 836 const uint32_t die_count = pos->second.count; 837 const uint32_t die_size = pos->second.byte_size; 838 839 statBySizeMap.insert(pos); 840 total_die_count += die_count; 841 total_die_size += die_size; 842 DW_TAG_CategoryEnum category = get_tag_category(pos->first); 843 total_category_sizes[category] += die_size; 844 total_category_count[category] += die_count; 845 } 846 847 float total_die_size_float = total_die_size; 848 849 DIEStatBySizeMap::const_reverse_iterator size_pos; 850 DIEStatBySizeMap::const_reverse_iterator size_pos_end = statBySizeMap.rend(); 851 float percentage; 852 for (size_pos = statBySizeMap.rbegin(); size_pos != size_pos_end; ++size_pos) 853 { 854 pos = *size_pos; 855 856 const DIEStat& tag_stat = pos->second; 857 858 const uint32_t die_count = tag_stat.count; 859 const uint32_t die_size = tag_stat.byte_size; 860 percentage = ((float)die_size/total_die_size_float)*100.0; 861 s->Printf("%7u %8u %2.2f%% %s\n", die_count, die_size, percentage, DW_TAG_value_to_name(pos->first)); 862 863 const DwarfAttrStatMap& attr_stats = tag_stat.attr_stats; 864 if (!attr_stats.empty()) 865 { 866 typedef set<DwarfAttrStatMap::const_iterator, CompareAttrDIEStatSizes> DwarfAttrStatBySizeMap; 867 DwarfAttrStatBySizeMap attrStatBySizeMap; 868 DwarfAttrStatMap::const_iterator attr_stat_pos; 869 DwarfAttrStatMap::const_iterator attr_stat_pos_end = attr_stats.end(); 870 for (attr_stat_pos = attr_stats.begin(); attr_stat_pos != attr_stat_pos_end; ++attr_stat_pos) 871 { 872 attrStatBySizeMap.insert(attr_stat_pos); 873 } 874 875 DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos; 876 DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos_end = attrStatBySizeMap.rend(); 877 for (attr_size_pos = attrStatBySizeMap.rbegin(); attr_size_pos != attr_size_pos_end; ++attr_size_pos) 878 { 879 attr_stat_pos = *attr_size_pos; 880 percentage = ((float)attr_stat_pos->second.byte_size/die_size)*100.0; 881 s->Printf("%7u %8u %2.2f%% %s\n", attr_stat_pos->second.count, attr_stat_pos->second.byte_size, percentage, DW_AT_value_to_name(attr_stat_pos->first)); 882 } 883 s->EOL(); 884 } 885 } 886 887 s->Printf("-------- -------- -------- -------------------------------------------\n"); 888 s->Printf("%7u %8u 100.00%% Total for all DIEs\n", total_die_count, total_die_size); 889 890 float total_category_percentages[kNumTagCategories] = 891 { 892 ((float)total_category_sizes[TagCategoryVariable]/total_die_size_float)*100.0, 893 ((float)total_category_sizes[TagCategoryType]/total_die_size_float)*100.0, 894 ((float)total_category_sizes[TagCategoryProgram]/total_die_size_float)*100.0 895 }; 896 897 s->EOL(); 898 s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryVariable], total_category_sizes[TagCategoryVariable], total_category_percentages[TagCategoryVariable], "Total for variable related DIEs"); 899 s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryType], total_category_sizes[TagCategoryType], total_category_percentages[TagCategoryType], "Total for type related DIEs"); 900 s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryProgram], total_category_sizes[TagCategoryProgram], total_category_percentages[TagCategoryProgram], "Total for program related DIEs"); 901 s->Printf("\n\n"); 902} 903 904typedef struct DumpInfo 905{ 906 DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) : 907 strm(init_strm), 908 die_offset(off), 909 recurse_depth(depth), 910 found_depth(UINT32_MAX), 911 found_die(false), 912 ancestors() 913 { 914 } 915 Stream* strm; 916 const uint32_t die_offset; 917 const uint32_t recurse_depth; 918 uint32_t found_depth; 919 bool found_die; 920 std::vector<DWARFDebugInfoEntry> ancestors; 921 922 DISALLOW_COPY_AND_ASSIGN(DumpInfo); 923} DumpInfo; 924 925//---------------------------------------------------------------------- 926// DumpCallback 927// 928// A callback function for the static DWARFDebugInfo::Parse() function 929// that gets called each time a compile unit header or debug information 930// entry is successfully parsed. 931// 932// This function dump DWARF information and obey recurse depth and 933// whether a single DIE is to be dumped (or all of the data). 934//---------------------------------------------------------------------- 935static dw_offset_t DumpCallback 936( 937 SymbolFileDWARF* dwarf2Data, 938 DWARFCompileUnitSP& cu_sp, 939 DWARFDebugInfoEntry* die, 940 const dw_offset_t next_offset, 941 const uint32_t curr_depth, 942 void* userData 943) 944{ 945 DumpInfo* dumpInfo = (DumpInfo*)userData; 946 947 const DWARFCompileUnit* cu = cu_sp.get(); 948 949 Stream *s = dumpInfo->strm; 950 bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); 951 952 if (die) 953 { 954 // Are we dumping everything? 955 if (dumpInfo->die_offset == DW_INVALID_OFFSET) 956 { 957 // Yes we are dumping everything. Obey our recurse level though 958 if (curr_depth < dumpInfo->recurse_depth) 959 die->Dump(dwarf2Data, cu, *s, 0); 960 } 961 else 962 { 963 // We are dumping a specific DIE entry by offset 964 if (dumpInfo->die_offset == die->GetOffset()) 965 { 966 // We found the DIE we were looking for, dump it! 967 if (show_parents) 968 { 969 s->SetIndentLevel(0); 970 const uint32_t num_ancestors = dumpInfo->ancestors.size(); 971 if (num_ancestors > 0) 972 { 973 for (uint32_t i=0; i<num_ancestors-1; ++i) 974 { 975 dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); 976 s->IndentMore(); 977 } 978 } 979 } 980 981 dumpInfo->found_depth = curr_depth; 982 983 die->Dump(dwarf2Data, cu, *s, 0); 984 985 // Note that we found the DIE we were looking for 986 dumpInfo->found_die = true; 987 988 // Since we are dumping a single DIE, if there are no children we are done! 989 if (!die->HasChildren() || dumpInfo->recurse_depth == 0) 990 return DW_INVALID_OFFSET; // Return an invalid address to end parsing 991 } 992 else if (dumpInfo->found_die) 993 { 994 // Are we done with all the children? 995 if (curr_depth <= dumpInfo->found_depth) 996 return DW_INVALID_OFFSET; 997 998 // We have already found our DIE and are printing it's children. Obey 999 // our recurse depth and return an invalid offset if we get done 1000 // dumping all the the children 1001 if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) 1002 die->Dump(dwarf2Data, cu, *s, 0); 1003 } 1004 else if (dumpInfo->die_offset > die->GetOffset()) 1005 { 1006 if (show_parents) 1007 dumpInfo->ancestors.back() = *die; 1008 } 1009 } 1010 1011 // Keep up with our indent level 1012 if (die->IsNULL()) 1013 { 1014 if (show_parents) 1015 dumpInfo->ancestors.pop_back(); 1016 1017 if (curr_depth <= 1) 1018 return cu->GetNextCompileUnitOffset(); 1019 else 1020 s->IndentLess(); 1021 } 1022 else if (die->HasChildren()) 1023 { 1024 if (show_parents) 1025 { 1026 DWARFDebugInfoEntry null_die; 1027 dumpInfo->ancestors.push_back(null_die); 1028 } 1029 s->IndentMore(); 1030 } 1031 } 1032 else 1033 { 1034 if (cu == NULL) 1035 s->PutCString("NULL - cu"); 1036 // We have a compile unit, reset our indent level to zero just in case 1037 s->SetIndentLevel(0); 1038 1039 // See if we are dumping everything? 1040 if (dumpInfo->die_offset == DW_INVALID_OFFSET) 1041 { 1042 // We are dumping everything 1043 cu->Dump(s); 1044 return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit 1045 } 1046 else 1047 { 1048 if (show_parents) 1049 { 1050 dumpInfo->ancestors.clear(); 1051 dumpInfo->ancestors.resize(1); 1052 } 1053 1054 // We are dumping only a single DIE possibly with it's children and 1055 // we must find it's compile unit before we can dump it properly 1056 if (dumpInfo->die_offset < cu->GetFirstDIEOffset()) 1057 { 1058 // Not found, maybe the DIE offset provided wasn't correct? 1059 // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl; 1060 return DW_INVALID_OFFSET; 1061 } 1062 else 1063 { 1064 // See if the DIE is in this compile unit? 1065 if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) 1066 { 1067 // This DIE is in this compile unit! 1068 if (s->GetVerbose()) 1069 cu->Dump(s); // Dump the compile unit for the DIE in verbose mode 1070 1071 return next_offset; 1072 // // We found our compile unit that contains our DIE, just skip to dumping the requested DIE... 1073 // return dumpInfo->die_offset; 1074 } 1075 else 1076 { 1077 // Skip to the next compile unit as the DIE isn't in the current one! 1078 return cu->GetNextCompileUnitOffset(); 1079 } 1080 } 1081 } 1082 } 1083 1084 // Just return the current offset to parse the next CU or DIE entry 1085 return next_offset; 1086} 1087 1088//---------------------------------------------------------------------- 1089// Dump 1090// 1091// Dump the information in the .debug_info section to the specified 1092// ostream. If die_offset is valid, a single DIE will be dumped. If the 1093// die_offset is invalid, all the DWARF information will be dumped. Both 1094// cases will obey a "recurse_depth" or how deep to traverse into the 1095// children of each DIE entry. A recurse_depth of zero will dump all 1096// compile unit headers. A recurse_depth of 1 will dump all compile unit 1097// headers and the DW_TAG_compile unit tags. A depth of 2 will also 1098// dump all types and functions. 1099//---------------------------------------------------------------------- 1100void 1101DWARFDebugInfo::Dump 1102( 1103 Stream *s, 1104 SymbolFileDWARF* dwarf2Data, 1105 const uint32_t die_offset, 1106 const uint32_t recurse_depth 1107) 1108{ 1109 DumpInfo dumpInfo(s, die_offset, recurse_depth); 1110 s->PutCString(".debug_info contents"); 1111 if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) 1112 { 1113 if (die_offset == DW_INVALID_OFFSET) 1114 s->PutCString(":\n"); 1115 else 1116 { 1117 s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset); 1118 if (recurse_depth != UINT32_MAX) 1119 s->Printf(" recursing %u levels deep.", recurse_depth); 1120 s->EOL(); 1121 } 1122 } 1123 else 1124 { 1125 s->PutCString(": < EMPTY >\n"); 1126 return; 1127 } 1128 DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo); 1129} 1130 1131 1132//---------------------------------------------------------------------- 1133// Dump 1134// 1135// Dump the contents of this DWARFDebugInfo object as has been parsed 1136// and/or modified after it has been parsed. 1137//---------------------------------------------------------------------- 1138void 1139DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth) 1140{ 1141 DumpInfo dumpInfo(s, die_offset, recurse_depth); 1142 1143 s->PutCString("Dumping .debug_info section from internal representation\n"); 1144 1145 CompileUnitColl::const_iterator pos; 1146 uint32_t curr_depth = 0; 1147 ParseCompileUnitHeadersIfNeeded(); 1148 for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) 1149 { 1150 const DWARFCompileUnitSP& cu_sp = *pos; 1151 DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo); 1152 cu_sp->DIE()->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth); 1153 } 1154} 1155 1156 1157//---------------------------------------------------------------------- 1158// FindCallbackString 1159// 1160// A callback function for the static DWARFDebugInfo::Parse() function 1161// that gets called each time a compile unit header or debug information 1162// entry is successfully parsed. 1163// 1164// This function will find the die_offset of any items whose DW_AT_name 1165// matches the given string 1166//---------------------------------------------------------------------- 1167typedef struct FindCallbackStringInfoTag 1168{ 1169 const char* name; 1170 bool ignore_case; 1171 RegularExpression* regex; 1172 vector<dw_offset_t>& die_offsets; 1173} FindCallbackStringInfo; 1174 1175static dw_offset_t FindCallbackString 1176( 1177 SymbolFileDWARF* dwarf2Data, 1178 DWARFCompileUnitSP& cu_sp, 1179 DWARFDebugInfoEntry* die, 1180 const dw_offset_t next_offset, 1181 const uint32_t curr_depth, 1182 void* userData 1183) 1184{ 1185 FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData; 1186 const DWARFCompileUnit* cu = cu_sp.get(); 1187 1188 if (die) 1189 { 1190 const char* die_name = die->GetName(dwarf2Data, cu); 1191 if (die_name) 1192 { 1193 if (info->regex) 1194 { 1195 if (info->regex->Execute(die_name)) 1196 info->die_offsets.push_back(die->GetOffset()); 1197 } 1198 else 1199 { 1200 if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0) 1201 info->die_offsets.push_back(die->GetOffset()); 1202 } 1203 } 1204 } 1205 1206 // Just return the current offset to parse the next CU or DIE entry 1207 return next_offset; 1208} 1209 1210//---------------------------------------------------------------------- 1211// Find 1212// 1213// Finds all DIE that have a specific DW_AT_name attribute by manually 1214// searching through the debug information (not using the 1215// .debug_pubnames section). The string must match the entire name 1216// and case sensitive searches are an option. 1217//---------------------------------------------------------------------- 1218bool 1219DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const 1220{ 1221 die_offsets.clear(); 1222 if (name && name[0]) 1223 { 1224 FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets }; 1225 DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 1226 } 1227 return !die_offsets.empty(); 1228} 1229 1230//---------------------------------------------------------------------- 1231// Find 1232// 1233// Finds all DIE that have a specific DW_AT_name attribute by manually 1234// searching through the debug information (not using the 1235// .debug_pubnames section). The string must match the supplied regular 1236// expression. 1237//---------------------------------------------------------------------- 1238bool 1239DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const 1240{ 1241 die_offsets.clear(); 1242 FindCallbackStringInfo info = { NULL, false, &re, die_offsets }; 1243 DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 1244 return !die_offsets.empty(); 1245} 1246