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 27 using namespace lldb; 28 using namespace lldb_private; 29 using namespace std; 30 31 //---------------------------------------------------------------------- 32 // Constructor 33 //---------------------------------------------------------------------- 34 DWARFDebugInfo::DWARFDebugInfo() : 35 m_dwarf2Data(NULL), 36 m_compile_units(), 37 m_cu_aranges_ap () 38 { 39 } 40 41 //---------------------------------------------------------------------- 42 // SetDwarfData 43 //---------------------------------------------------------------------- 44 void 45 DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data) 46 { 47 m_dwarf2Data = dwarf2Data; 48 m_compile_units.clear(); 49 } 50 51 52 DWARFDebugAranges & 53 DWARFDebugInfo::GetCompileUnitAranges () 54 { 55 if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) 56 { 57 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 58 59 m_cu_aranges_ap.reset (new DWARFDebugAranges()); 60 const DWARFDataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data(); 61 if (debug_aranges_data.GetByteSize() > 0) 62 { 63 if (log) 64 log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from .debug_aranges", 65 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 66 m_cu_aranges_ap->Extract (debug_aranges_data); 67 68 } 69 70 // Make a list of all CUs represented by the arange data in the file. 71 std::set<dw_offset_t> cus_with_data; 72 for (size_t n=0;n<m_cu_aranges_ap.get()->GetNumRanges();n++) 73 { 74 dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n); 75 if (offset != DW_INVALID_OFFSET) 76 cus_with_data.insert (offset); 77 } 78 79 // Manually build arange data for everything that wasn't in the .debug_aranges table. 80 bool printed = false; 81 const size_t num_compile_units = GetNumCompileUnits(); 82 for (size_t idx = 0; idx < num_compile_units; ++idx) 83 { 84 DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx); 85 86 dw_offset_t offset = cu->GetOffset(); 87 if (cus_with_data.find(offset) == cus_with_data.end()) 88 { 89 if (log) 90 { 91 if (!printed) 92 log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", 93 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 94 printed = true; 95 } 96 cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get()); 97 } 98 } 99 100 const bool minimize = true; 101 m_cu_aranges_ap->Sort (minimize); 102 } 103 return *m_cu_aranges_ap.get(); 104 } 105 106 107 //---------------------------------------------------------------------- 108 // LookupAddress 109 //---------------------------------------------------------------------- 110 bool 111 DWARFDebugInfo::LookupAddress 112 ( 113 const dw_addr_t address, 114 const dw_offset_t hint_die_offset, 115 DWARFCompileUnitSP& cu_sp, 116 DWARFDebugInfoEntry** function_die, 117 DWARFDebugInfoEntry** block_die 118 ) 119 { 120 121 if (hint_die_offset != DW_INVALID_OFFSET) 122 cu_sp = GetCompileUnit(hint_die_offset); 123 else 124 { 125 DWARFDebugAranges &cu_aranges = GetCompileUnitAranges (); 126 const dw_offset_t cu_offset = cu_aranges.FindAddress (address); 127 cu_sp = GetCompileUnit(cu_offset); 128 } 129 130 if (cu_sp.get()) 131 { 132 if (cu_sp->LookupAddress(address, function_die, block_die)) 133 return true; 134 cu_sp.reset(); 135 } 136 else 137 { 138 // The hint_die_offset may have been a pointer to the actual item that 139 // we are looking for 140 DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp); 141 if (die_ptr) 142 { 143 if (cu_sp.get()) 144 { 145 if (function_die || block_die) 146 return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die); 147 148 // We only wanted the compile unit that contained this address 149 return true; 150 } 151 } 152 } 153 return false; 154 } 155 156 157 void 158 DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() 159 { 160 if (m_compile_units.empty()) 161 { 162 if (m_dwarf2Data != NULL) 163 { 164 lldb::offset_t offset = 0; 165 const DWARFDataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data(); 166 while (debug_info_data.ValidOffset(offset)) 167 { 168 DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); 169 // Out of memory? 170 if (cu_sp.get() == NULL) 171 break; 172 173 if (cu_sp->Extract(debug_info_data, &offset) == false) 174 break; 175 176 m_compile_units.push_back(cu_sp); 177 178 offset = cu_sp->GetNextCompileUnitOffset(); 179 } 180 } 181 } 182 } 183 184 size_t 185 DWARFDebugInfo::GetNumCompileUnits() 186 { 187 ParseCompileUnitHeadersIfNeeded(); 188 return m_compile_units.size(); 189 } 190 191 DWARFCompileUnit* 192 DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) 193 { 194 DWARFCompileUnit* cu = NULL; 195 if (idx < GetNumCompileUnits()) 196 cu = m_compile_units[idx].get(); 197 return cu; 198 } 199 200 bool 201 DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const 202 { 203 // Not a verify efficient function, but it is handy for use in assertions 204 // to make sure that a compile unit comes from a debug information file. 205 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 206 CompileUnitColl::const_iterator pos; 207 208 for (pos = m_compile_units.begin(); pos != end_pos; ++pos) 209 { 210 if (pos->get() == cu) 211 return true; 212 } 213 return false; 214 } 215 216 217 static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b) 218 { 219 return a->GetOffset() < b->GetOffset(); 220 } 221 222 223 static int 224 CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem) 225 { 226 const dw_offset_t key_cu_offset = *(dw_offset_t*) key; 227 const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset(); 228 if (key_cu_offset < cu_offset) 229 return -1; 230 if (key_cu_offset > cu_offset) 231 return 1; 232 return 0; 233 } 234 235 DWARFCompileUnitSP 236 DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) 237 { 238 DWARFCompileUnitSP cu_sp; 239 uint32_t cu_idx = DW_INVALID_INDEX; 240 if (cu_offset != DW_INVALID_OFFSET) 241 { 242 ParseCompileUnitHeadersIfNeeded(); 243 244 DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset); 245 if (match) 246 { 247 cu_sp = *match; 248 cu_idx = match - &m_compile_units[0]; 249 } 250 } 251 if (idx_ptr) 252 *idx_ptr = cu_idx; 253 return cu_sp; 254 } 255 256 DWARFCompileUnitSP 257 DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) 258 { 259 DWARFCompileUnitSP cu_sp; 260 if (die_offset != DW_INVALID_OFFSET) 261 { 262 ParseCompileUnitHeadersIfNeeded(); 263 264 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 265 CompileUnitColl::const_iterator pos; 266 267 for (pos = m_compile_units.begin(); pos != end_pos; ++pos) 268 { 269 dw_offset_t cu_start_offset = (*pos)->GetOffset(); 270 dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset(); 271 if (cu_start_offset <= die_offset && die_offset < cu_end_offset) 272 { 273 cu_sp = *pos; 274 break; 275 } 276 } 277 } 278 return cu_sp; 279 } 280 281 //---------------------------------------------------------------------- 282 // Compare function DWARFDebugAranges::Range structures 283 //---------------------------------------------------------------------- 284 static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 285 { 286 return die1.GetOffset() < die2.GetOffset(); 287 } 288 289 290 //---------------------------------------------------------------------- 291 // GetDIE() 292 // 293 // Get the DIE (Debug Information Entry) with the specified offset. 294 //---------------------------------------------------------------------- 295 DWARFDebugInfoEntry* 296 DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 297 { 298 DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 299 if (cu_sp_ptr) 300 *cu_sp_ptr = cu_sp; 301 if (cu_sp.get()) 302 return cu_sp->GetDIEPtr(die_offset); 303 return NULL; // Not found in any compile units 304 } 305 306 DWARFDebugInfoEntry* 307 DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle) 308 { 309 assert (cu_handle); 310 DWARFDebugInfoEntry* die = NULL; 311 if (*cu_handle) 312 die = (*cu_handle)->GetDIEPtr(die_offset); 313 314 if (die == NULL) 315 { 316 DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset)); 317 if (cu_sp.get()) 318 { 319 *cu_handle = cu_sp.get(); 320 die = cu_sp->GetDIEPtr(die_offset); 321 } 322 } 323 if (die == NULL) 324 *cu_handle = NULL; 325 return die; 326 } 327 328 329 const DWARFDebugInfoEntry* 330 DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 331 { 332 DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 333 if (cu_sp_ptr) 334 *cu_sp_ptr = cu_sp; 335 if (cu_sp.get()) 336 return cu_sp->GetDIEPtrContainingOffset(die_offset); 337 338 return NULL; // Not found in any compile units 339 340 } 341 342 //---------------------------------------------------------------------- 343 // DWARFDebugInfo_ParseCallback 344 // 345 // A callback function for the static DWARFDebugInfo::Parse() function 346 // that gets parses all compile units and DIE's into an internate 347 // representation for further modification. 348 //---------------------------------------------------------------------- 349 350 static dw_offset_t 351 DWARFDebugInfo_ParseCallback 352 ( 353 SymbolFileDWARF* dwarf2Data, 354 DWARFCompileUnitSP& cu_sp, 355 DWARFDebugInfoEntry* die, 356 const dw_offset_t next_offset, 357 const uint32_t curr_depth, 358 void* userData 359 ) 360 { 361 DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData; 362 DWARFCompileUnit* cu = cu_sp.get(); 363 if (die) 364 { 365 cu->AddDIE(*die); 366 } 367 else if (cu) 368 { 369 debug_info->AddCompileUnit(cu_sp); 370 } 371 372 // Just return the current offset to parse the next CU or DIE entry 373 return next_offset; 374 } 375 376 //---------------------------------------------------------------------- 377 // AddCompileUnit 378 //---------------------------------------------------------------------- 379 void 380 DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu) 381 { 382 m_compile_units.push_back(cu); 383 } 384 385 /* 386 void 387 DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die) 388 { 389 m_die_array.push_back(die); 390 } 391 */ 392 393 394 395 396 //---------------------------------------------------------------------- 397 // Parse 398 // 399 // Parses the .debug_info section and uses the .debug_abbrev section 400 // and various other sections in the SymbolFileDWARF class and calls the 401 // supplied callback function each time a compile unit header, or debug 402 // information entry is successfully parsed. This function can be used 403 // for different tasks such as parsing the file contents into a 404 // structured data, dumping, verifying and much more. 405 //---------------------------------------------------------------------- 406 void 407 DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData) 408 { 409 if (dwarf2Data) 410 { 411 lldb::offset_t offset = 0; 412 uint32_t depth = 0; 413 DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); 414 if (cu.get() == NULL) 415 return; 416 DWARFDebugInfoEntry die; 417 418 while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) 419 { 420 const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); 421 422 depth = 0; 423 // Call the callback function with no DIE pointer for the compile unit 424 // and get the offset that we are to continue to parse from 425 offset = callback(dwarf2Data, cu, NULL, offset, depth, userData); 426 427 // Make sure we are within our compile unit 428 if (offset < next_cu_offset) 429 { 430 // We are in our compile unit, parse starting at the offset 431 // we were told to parse 432 bool done = false; 433 while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) 434 { 435 // Call the callback function with DIE pointer that falls within the compile unit 436 offset = callback(dwarf2Data, cu, &die, offset, depth, userData); 437 438 if (die.IsNULL()) 439 { 440 if (depth) 441 --depth; 442 else 443 done = true; // We are done with this compile unit! 444 } 445 else if (die.HasChildren()) 446 ++depth; 447 } 448 } 449 450 // Make sure the offset returned is valid, and if not stop parsing. 451 // Returning DW_INVALID_OFFSET from this callback is a good way to end 452 // all parsing 453 if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) 454 break; 455 456 // See if during the callback anyone retained a copy of the compile 457 // unit other than ourselves and if so, let whomever did own the object 458 // and create a new one for our own use! 459 if (!cu.unique()) 460 cu.reset(new DWARFCompileUnit(dwarf2Data)); 461 462 463 // Make sure we start on a proper 464 offset = next_cu_offset; 465 } 466 } 467 } 468 469 typedef struct DumpInfo 470 { 471 DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) : 472 strm(init_strm), 473 die_offset(off), 474 recurse_depth(depth), 475 found_depth(UINT32_MAX), 476 found_die(false), 477 ancestors() 478 { 479 } 480 Stream* strm; 481 const uint32_t die_offset; 482 const uint32_t recurse_depth; 483 uint32_t found_depth; 484 bool found_die; 485 std::vector<DWARFDebugInfoEntry> ancestors; 486 487 DISALLOW_COPY_AND_ASSIGN(DumpInfo); 488 } DumpInfo; 489 490 //---------------------------------------------------------------------- 491 // DumpCallback 492 // 493 // A callback function for the static DWARFDebugInfo::Parse() function 494 // that gets called each time a compile unit header or debug information 495 // entry is successfully parsed. 496 // 497 // This function dump DWARF information and obey recurse depth and 498 // whether a single DIE is to be dumped (or all of the data). 499 //---------------------------------------------------------------------- 500 static dw_offset_t DumpCallback 501 ( 502 SymbolFileDWARF* dwarf2Data, 503 DWARFCompileUnitSP& cu_sp, 504 DWARFDebugInfoEntry* die, 505 const dw_offset_t next_offset, 506 const uint32_t curr_depth, 507 void* userData 508 ) 509 { 510 DumpInfo* dumpInfo = (DumpInfo*)userData; 511 512 const DWARFCompileUnit* cu = cu_sp.get(); 513 514 Stream *s = dumpInfo->strm; 515 bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); 516 517 if (die) 518 { 519 // Are we dumping everything? 520 if (dumpInfo->die_offset == DW_INVALID_OFFSET) 521 { 522 // Yes we are dumping everything. Obey our recurse level though 523 if (curr_depth < dumpInfo->recurse_depth) 524 die->Dump(dwarf2Data, cu, *s, 0); 525 } 526 else 527 { 528 // We are dumping a specific DIE entry by offset 529 if (dumpInfo->die_offset == die->GetOffset()) 530 { 531 // We found the DIE we were looking for, dump it! 532 if (show_parents) 533 { 534 s->SetIndentLevel(0); 535 const uint32_t num_ancestors = dumpInfo->ancestors.size(); 536 if (num_ancestors > 0) 537 { 538 for (uint32_t i=0; i<num_ancestors-1; ++i) 539 { 540 dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); 541 s->IndentMore(); 542 } 543 } 544 } 545 546 dumpInfo->found_depth = curr_depth; 547 548 die->Dump(dwarf2Data, cu, *s, 0); 549 550 // Note that we found the DIE we were looking for 551 dumpInfo->found_die = true; 552 553 // Since we are dumping a single DIE, if there are no children we are done! 554 if (!die->HasChildren() || dumpInfo->recurse_depth == 0) 555 return DW_INVALID_OFFSET; // Return an invalid address to end parsing 556 } 557 else if (dumpInfo->found_die) 558 { 559 // Are we done with all the children? 560 if (curr_depth <= dumpInfo->found_depth) 561 return DW_INVALID_OFFSET; 562 563 // We have already found our DIE and are printing it's children. Obey 564 // our recurse depth and return an invalid offset if we get done 565 // dumping all the the children 566 if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) 567 die->Dump(dwarf2Data, cu, *s, 0); 568 } 569 else if (dumpInfo->die_offset > die->GetOffset()) 570 { 571 if (show_parents) 572 dumpInfo->ancestors.back() = *die; 573 } 574 } 575 576 // Keep up with our indent level 577 if (die->IsNULL()) 578 { 579 if (show_parents) 580 dumpInfo->ancestors.pop_back(); 581 582 if (curr_depth <= 1) 583 return cu->GetNextCompileUnitOffset(); 584 else 585 s->IndentLess(); 586 } 587 else if (die->HasChildren()) 588 { 589 if (show_parents) 590 { 591 DWARFDebugInfoEntry null_die; 592 dumpInfo->ancestors.push_back(null_die); 593 } 594 s->IndentMore(); 595 } 596 } 597 else 598 { 599 if (cu == NULL) 600 s->PutCString("NULL - cu"); 601 // We have a compile unit, reset our indent level to zero just in case 602 s->SetIndentLevel(0); 603 604 // See if we are dumping everything? 605 if (dumpInfo->die_offset == DW_INVALID_OFFSET) 606 { 607 // We are dumping everything 608 cu->Dump(s); 609 return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit 610 } 611 else 612 { 613 if (show_parents) 614 { 615 dumpInfo->ancestors.clear(); 616 dumpInfo->ancestors.resize(1); 617 } 618 619 // We are dumping only a single DIE possibly with it's children and 620 // we must find it's compile unit before we can dump it properly 621 if (dumpInfo->die_offset < cu->GetFirstDIEOffset()) 622 { 623 // Not found, maybe the DIE offset provided wasn't correct? 624 // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl; 625 return DW_INVALID_OFFSET; 626 } 627 else 628 { 629 // See if the DIE is in this compile unit? 630 if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) 631 { 632 // This DIE is in this compile unit! 633 if (s->GetVerbose()) 634 cu->Dump(s); // Dump the compile unit for the DIE in verbose mode 635 636 return next_offset; 637 // // We found our compile unit that contains our DIE, just skip to dumping the requested DIE... 638 // return dumpInfo->die_offset; 639 } 640 else 641 { 642 // Skip to the next compile unit as the DIE isn't in the current one! 643 return cu->GetNextCompileUnitOffset(); 644 } 645 } 646 } 647 } 648 649 // Just return the current offset to parse the next CU or DIE entry 650 return next_offset; 651 } 652 653 //---------------------------------------------------------------------- 654 // Dump 655 // 656 // Dump the information in the .debug_info section to the specified 657 // ostream. If die_offset is valid, a single DIE will be dumped. If the 658 // die_offset is invalid, all the DWARF information will be dumped. Both 659 // cases will obey a "recurse_depth" or how deep to traverse into the 660 // children of each DIE entry. A recurse_depth of zero will dump all 661 // compile unit headers. A recurse_depth of 1 will dump all compile unit 662 // headers and the DW_TAG_compile unit tags. A depth of 2 will also 663 // dump all types and functions. 664 //---------------------------------------------------------------------- 665 void 666 DWARFDebugInfo::Dump 667 ( 668 Stream *s, 669 SymbolFileDWARF* dwarf2Data, 670 const uint32_t die_offset, 671 const uint32_t recurse_depth 672 ) 673 { 674 DumpInfo dumpInfo(s, die_offset, recurse_depth); 675 s->PutCString(".debug_info contents"); 676 if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) 677 { 678 if (die_offset == DW_INVALID_OFFSET) 679 s->PutCString(":\n"); 680 else 681 { 682 s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset); 683 if (recurse_depth != UINT32_MAX) 684 s->Printf(" recursing %u levels deep.", recurse_depth); 685 s->EOL(); 686 } 687 } 688 else 689 { 690 s->PutCString(": < EMPTY >\n"); 691 return; 692 } 693 DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo); 694 } 695 696 697 //---------------------------------------------------------------------- 698 // Dump 699 // 700 // Dump the contents of this DWARFDebugInfo object as has been parsed 701 // and/or modified after it has been parsed. 702 //---------------------------------------------------------------------- 703 void 704 DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth) 705 { 706 DumpInfo dumpInfo(s, die_offset, recurse_depth); 707 708 s->PutCString("Dumping .debug_info section from internal representation\n"); 709 710 CompileUnitColl::const_iterator pos; 711 uint32_t curr_depth = 0; 712 ParseCompileUnitHeadersIfNeeded(); 713 for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) 714 { 715 const DWARFCompileUnitSP& cu_sp = *pos; 716 DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo); 717 718 const DWARFDebugInfoEntry* die = cu_sp->DIE(); 719 if (die) 720 die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth); 721 } 722 } 723 724 725 //---------------------------------------------------------------------- 726 // FindCallbackString 727 // 728 // A callback function for the static DWARFDebugInfo::Parse() function 729 // that gets called each time a compile unit header or debug information 730 // entry is successfully parsed. 731 // 732 // This function will find the die_offset of any items whose DW_AT_name 733 // matches the given string 734 //---------------------------------------------------------------------- 735 typedef struct FindCallbackStringInfoTag 736 { 737 const char* name; 738 bool ignore_case; 739 RegularExpression* regex; 740 vector<dw_offset_t>& die_offsets; 741 } FindCallbackStringInfo; 742 743 static dw_offset_t FindCallbackString 744 ( 745 SymbolFileDWARF* dwarf2Data, 746 DWARFCompileUnitSP& cu_sp, 747 DWARFDebugInfoEntry* die, 748 const dw_offset_t next_offset, 749 const uint32_t curr_depth, 750 void* userData 751 ) 752 { 753 FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData; 754 const DWARFCompileUnit* cu = cu_sp.get(); 755 756 if (die) 757 { 758 const char* die_name = die->GetName(dwarf2Data, cu); 759 if (die_name) 760 { 761 if (info->regex) 762 { 763 if (info->regex->Execute(die_name)) 764 info->die_offsets.push_back(die->GetOffset()); 765 } 766 else 767 { 768 if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0) 769 info->die_offsets.push_back(die->GetOffset()); 770 } 771 } 772 } 773 774 // Just return the current offset to parse the next CU or DIE entry 775 return next_offset; 776 } 777 778 //---------------------------------------------------------------------- 779 // Find 780 // 781 // Finds all DIE that have a specific DW_AT_name attribute by manually 782 // searching through the debug information (not using the 783 // .debug_pubnames section). The string must match the entire name 784 // and case sensitive searches are an option. 785 //---------------------------------------------------------------------- 786 bool 787 DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const 788 { 789 die_offsets.clear(); 790 if (name && name[0]) 791 { 792 FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets }; 793 DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 794 } 795 return !die_offsets.empty(); 796 } 797 798 //---------------------------------------------------------------------- 799 // Find 800 // 801 // Finds all DIE that have a specific DW_AT_name attribute by manually 802 // searching through the debug information (not using the 803 // .debug_pubnames section). The string must match the supplied regular 804 // expression. 805 //---------------------------------------------------------------------- 806 bool 807 DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const 808 { 809 die_offsets.clear(); 810 FindCallbackStringInfo info = { NULL, false, &re, die_offsets }; 811 DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 812 return !die_offsets.empty(); 813 } 814