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