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