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