1254721Semaste//===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "SymbolFileDWARF.h" 11254721Semaste 12254721Semaste#include <algorithm> 13254721Semaste#include <set> 14254721Semaste 15254721Semaste#include "lldb/Core/RegularExpression.h" 16254721Semaste#include "lldb/Core/Stream.h" 17254721Semaste#include "lldb/Symbol/ObjectFile.h" 18254721Semaste 19254721Semaste#include "DWARFDebugAranges.h" 20254721Semaste#include "DWARFDebugInfo.h" 21254721Semaste#include "DWARFCompileUnit.h" 22254721Semaste#include "DWARFDebugAranges.h" 23254721Semaste#include "DWARFDebugInfoEntry.h" 24254721Semaste#include "DWARFFormValue.h" 25254721Semaste#include "LogChannelDWARF.h" 26254721Semaste 27254721Semasteusing namespace lldb; 28254721Semasteusing namespace lldb_private; 29254721Semasteusing namespace std; 30254721Semaste 31254721Semaste//---------------------------------------------------------------------- 32254721Semaste// Constructor 33254721Semaste//---------------------------------------------------------------------- 34254721SemasteDWARFDebugInfo::DWARFDebugInfo() : 35254721Semaste m_dwarf2Data(NULL), 36254721Semaste m_compile_units(), 37254721Semaste m_cu_aranges_ap () 38254721Semaste{ 39254721Semaste} 40254721Semaste 41254721Semaste//---------------------------------------------------------------------- 42254721Semaste// SetDwarfData 43254721Semaste//---------------------------------------------------------------------- 44254721Semastevoid 45254721SemasteDWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data) 46254721Semaste{ 47254721Semaste m_dwarf2Data = dwarf2Data; 48254721Semaste m_compile_units.clear(); 49254721Semaste} 50254721Semaste 51254721Semaste 52254721SemasteDWARFDebugAranges & 53254721SemasteDWARFDebugInfo::GetCompileUnitAranges () 54254721Semaste{ 55254721Semaste if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) 56254721Semaste { 57254721Semaste Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 58254721Semaste 59254721Semaste m_cu_aranges_ap.reset (new DWARFDebugAranges()); 60254721Semaste const DataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data(); 61254721Semaste if (debug_aranges_data.GetByteSize() > 0) 62254721Semaste { 63254721Semaste if (log) 64254721Semaste log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from .debug_aranges", 65254721Semaste m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 66254721Semaste m_cu_aranges_ap->Extract (debug_aranges_data); 67254721Semaste 68254721Semaste } 69254721Semaste else 70254721Semaste { 71254721Semaste if (log) 72254721Semaste log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", 73254721Semaste m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 74254721Semaste const size_t num_compile_units = GetNumCompileUnits(); 75254721Semaste const bool clear_dies_if_already_not_parsed = true; 76254721Semaste for (size_t idx = 0; idx < num_compile_units; ++idx) 77254721Semaste { 78254721Semaste DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx); 79254721Semaste if (cu) 80254721Semaste cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed); 81254721Semaste } 82254721Semaste } 83254721Semaste 84254721Semaste const bool minimize = true; 85254721Semaste m_cu_aranges_ap->Sort (minimize); 86254721Semaste } 87254721Semaste return *m_cu_aranges_ap.get(); 88254721Semaste} 89254721Semaste 90254721Semaste 91254721Semaste//---------------------------------------------------------------------- 92254721Semaste// LookupAddress 93254721Semaste//---------------------------------------------------------------------- 94254721Semastebool 95254721SemasteDWARFDebugInfo::LookupAddress 96254721Semaste( 97254721Semaste const dw_addr_t address, 98254721Semaste const dw_offset_t hint_die_offset, 99254721Semaste DWARFCompileUnitSP& cu_sp, 100254721Semaste DWARFDebugInfoEntry** function_die, 101254721Semaste DWARFDebugInfoEntry** block_die 102254721Semaste) 103254721Semaste{ 104254721Semaste 105254721Semaste if (hint_die_offset != DW_INVALID_OFFSET) 106254721Semaste cu_sp = GetCompileUnit(hint_die_offset); 107254721Semaste else 108254721Semaste { 109254721Semaste DWARFDebugAranges &cu_aranges = GetCompileUnitAranges (); 110254721Semaste const dw_offset_t cu_offset = cu_aranges.FindAddress (address); 111254721Semaste cu_sp = GetCompileUnit(cu_offset); 112254721Semaste } 113254721Semaste 114254721Semaste if (cu_sp.get()) 115254721Semaste { 116254721Semaste if (cu_sp->LookupAddress(address, function_die, block_die)) 117254721Semaste return true; 118254721Semaste cu_sp.reset(); 119254721Semaste } 120254721Semaste else 121254721Semaste { 122254721Semaste // The hint_die_offset may have been a pointer to the actual item that 123254721Semaste // we are looking for 124254721Semaste DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp); 125254721Semaste if (die_ptr) 126254721Semaste { 127254721Semaste if (cu_sp.get()) 128254721Semaste { 129254721Semaste if (function_die || block_die) 130254721Semaste return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die); 131254721Semaste 132254721Semaste // We only wanted the compile unit that contained this address 133254721Semaste return true; 134254721Semaste } 135254721Semaste } 136254721Semaste } 137254721Semaste return false; 138254721Semaste} 139254721Semaste 140254721Semaste 141254721Semastevoid 142254721SemasteDWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() 143254721Semaste{ 144254721Semaste if (m_compile_units.empty()) 145254721Semaste { 146254721Semaste if (m_dwarf2Data != NULL) 147254721Semaste { 148254721Semaste lldb::offset_t offset = 0; 149254721Semaste const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data(); 150254721Semaste while (debug_info_data.ValidOffset(offset)) 151254721Semaste { 152254721Semaste DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); 153254721Semaste // Out of memory? 154254721Semaste if (cu_sp.get() == NULL) 155254721Semaste break; 156254721Semaste 157254721Semaste if (cu_sp->Extract(debug_info_data, &offset) == false) 158254721Semaste break; 159254721Semaste 160254721Semaste m_compile_units.push_back(cu_sp); 161254721Semaste 162254721Semaste offset = cu_sp->GetNextCompileUnitOffset(); 163254721Semaste } 164254721Semaste } 165254721Semaste } 166254721Semaste} 167254721Semaste 168254721Semastesize_t 169254721SemasteDWARFDebugInfo::GetNumCompileUnits() 170254721Semaste{ 171254721Semaste ParseCompileUnitHeadersIfNeeded(); 172254721Semaste return m_compile_units.size(); 173254721Semaste} 174254721Semaste 175254721SemasteDWARFCompileUnit* 176254721SemasteDWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) 177254721Semaste{ 178254721Semaste DWARFCompileUnit* cu = NULL; 179254721Semaste if (idx < GetNumCompileUnits()) 180254721Semaste cu = m_compile_units[idx].get(); 181254721Semaste return cu; 182254721Semaste} 183254721Semaste 184254721Semastebool 185254721SemasteDWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const 186254721Semaste{ 187254721Semaste // Not a verify efficient function, but it is handy for use in assertions 188254721Semaste // to make sure that a compile unit comes from a debug information file. 189254721Semaste CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 190254721Semaste CompileUnitColl::const_iterator pos; 191254721Semaste 192254721Semaste for (pos = m_compile_units.begin(); pos != end_pos; ++pos) 193254721Semaste { 194254721Semaste if (pos->get() == cu) 195254721Semaste return true; 196254721Semaste } 197254721Semaste return false; 198254721Semaste} 199254721Semaste 200254721Semaste 201254721Semastestatic bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b) 202254721Semaste{ 203254721Semaste return a->GetOffset() < b->GetOffset(); 204254721Semaste} 205254721Semaste 206254721Semaste 207254721Semastestatic int 208254721SemasteCompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem) 209254721Semaste{ 210254721Semaste const dw_offset_t key_cu_offset = *(dw_offset_t*) key; 211254721Semaste const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset(); 212254721Semaste if (key_cu_offset < cu_offset) 213254721Semaste return -1; 214254721Semaste if (key_cu_offset > cu_offset) 215254721Semaste return 1; 216254721Semaste return 0; 217254721Semaste} 218254721Semaste 219254721SemasteDWARFCompileUnitSP 220254721SemasteDWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) 221254721Semaste{ 222254721Semaste DWARFCompileUnitSP cu_sp; 223254721Semaste uint32_t cu_idx = DW_INVALID_INDEX; 224254721Semaste if (cu_offset != DW_INVALID_OFFSET) 225254721Semaste { 226254721Semaste ParseCompileUnitHeadersIfNeeded(); 227254721Semaste 228254721Semaste DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset); 229254721Semaste if (match) 230254721Semaste { 231254721Semaste cu_sp = *match; 232254721Semaste cu_idx = match - &m_compile_units[0]; 233254721Semaste } 234254721Semaste } 235254721Semaste if (idx_ptr) 236254721Semaste *idx_ptr = cu_idx; 237254721Semaste return cu_sp; 238254721Semaste} 239254721Semaste 240254721SemasteDWARFCompileUnitSP 241254721SemasteDWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) 242254721Semaste{ 243254721Semaste DWARFCompileUnitSP cu_sp; 244254721Semaste if (die_offset != DW_INVALID_OFFSET) 245254721Semaste { 246254721Semaste ParseCompileUnitHeadersIfNeeded(); 247254721Semaste 248254721Semaste CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 249254721Semaste CompileUnitColl::const_iterator pos; 250254721Semaste 251254721Semaste for (pos = m_compile_units.begin(); pos != end_pos; ++pos) 252254721Semaste { 253254721Semaste dw_offset_t cu_start_offset = (*pos)->GetOffset(); 254254721Semaste dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset(); 255254721Semaste if (cu_start_offset <= die_offset && die_offset < cu_end_offset) 256254721Semaste { 257254721Semaste cu_sp = *pos; 258254721Semaste break; 259254721Semaste } 260254721Semaste } 261254721Semaste } 262254721Semaste return cu_sp; 263254721Semaste} 264254721Semaste 265254721Semaste//---------------------------------------------------------------------- 266254721Semaste// Compare function DWARFDebugAranges::Range structures 267254721Semaste//---------------------------------------------------------------------- 268254721Semastestatic bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 269254721Semaste{ 270254721Semaste return die1.GetOffset() < die2.GetOffset(); 271254721Semaste} 272254721Semaste 273254721Semaste 274254721Semaste//---------------------------------------------------------------------- 275254721Semaste// GetDIE() 276254721Semaste// 277254721Semaste// Get the DIE (Debug Information Entry) with the specified offset. 278254721Semaste//---------------------------------------------------------------------- 279254721SemasteDWARFDebugInfoEntry* 280254721SemasteDWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 281254721Semaste{ 282254721Semaste DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 283254721Semaste if (cu_sp_ptr) 284254721Semaste *cu_sp_ptr = cu_sp; 285254721Semaste if (cu_sp.get()) 286254721Semaste return cu_sp->GetDIEPtr(die_offset); 287254721Semaste return NULL; // Not found in any compile units 288254721Semaste} 289254721Semaste 290254721SemasteDWARFDebugInfoEntry* 291254721SemasteDWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle) 292254721Semaste{ 293254721Semaste assert (cu_handle); 294254721Semaste DWARFDebugInfoEntry* die = NULL; 295254721Semaste if (*cu_handle) 296254721Semaste die = (*cu_handle)->GetDIEPtr(die_offset); 297254721Semaste 298254721Semaste if (die == NULL) 299254721Semaste { 300254721Semaste DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset)); 301254721Semaste if (cu_sp.get()) 302254721Semaste { 303254721Semaste *cu_handle = cu_sp.get(); 304254721Semaste die = cu_sp->GetDIEPtr(die_offset); 305254721Semaste } 306254721Semaste } 307254721Semaste if (die == NULL) 308254721Semaste *cu_handle = NULL; 309254721Semaste return die; 310254721Semaste} 311254721Semaste 312254721Semaste 313254721Semasteconst DWARFDebugInfoEntry* 314254721SemasteDWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) 315254721Semaste{ 316254721Semaste DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); 317254721Semaste if (cu_sp_ptr) 318254721Semaste *cu_sp_ptr = cu_sp; 319254721Semaste if (cu_sp.get()) 320254721Semaste return cu_sp->GetDIEPtrContainingOffset(die_offset); 321254721Semaste 322254721Semaste return NULL; // Not found in any compile units 323254721Semaste 324254721Semaste} 325254721Semaste 326254721Semaste//---------------------------------------------------------------------- 327254721Semaste// DWARFDebugInfo_ParseCallback 328254721Semaste// 329254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function 330254721Semaste// that gets parses all compile units and DIE's into an internate 331254721Semaste// representation for further modification. 332254721Semaste//---------------------------------------------------------------------- 333254721Semaste 334254721Semastestatic dw_offset_t 335254721SemasteDWARFDebugInfo_ParseCallback 336254721Semaste( 337254721Semaste SymbolFileDWARF* dwarf2Data, 338254721Semaste DWARFCompileUnitSP& cu_sp, 339254721Semaste DWARFDebugInfoEntry* die, 340254721Semaste const dw_offset_t next_offset, 341254721Semaste const uint32_t curr_depth, 342254721Semaste void* userData 343254721Semaste) 344254721Semaste{ 345254721Semaste DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData; 346254721Semaste DWARFCompileUnit* cu = cu_sp.get(); 347254721Semaste if (die) 348254721Semaste { 349254721Semaste cu->AddDIE(*die); 350254721Semaste } 351254721Semaste else if (cu) 352254721Semaste { 353254721Semaste debug_info->AddCompileUnit(cu_sp); 354254721Semaste } 355254721Semaste 356254721Semaste // Just return the current offset to parse the next CU or DIE entry 357254721Semaste return next_offset; 358254721Semaste} 359254721Semaste 360254721Semaste//---------------------------------------------------------------------- 361254721Semaste// AddCompileUnit 362254721Semaste//---------------------------------------------------------------------- 363254721Semastevoid 364254721SemasteDWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu) 365254721Semaste{ 366254721Semaste m_compile_units.push_back(cu); 367254721Semaste} 368254721Semaste 369254721Semaste/* 370254721Semastevoid 371254721SemasteDWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die) 372254721Semaste{ 373254721Semaste m_die_array.push_back(die); 374254721Semaste} 375254721Semaste*/ 376254721Semaste 377254721Semaste 378254721Semaste 379254721Semaste 380254721Semaste//---------------------------------------------------------------------- 381254721Semaste// Parse 382254721Semaste// 383254721Semaste// Parses the .debug_info section and uses the .debug_abbrev section 384254721Semaste// and various other sections in the SymbolFileDWARF class and calls the 385254721Semaste// supplied callback function each time a compile unit header, or debug 386254721Semaste// information entry is successfully parsed. This function can be used 387254721Semaste// for different tasks such as parsing the file contents into a 388254721Semaste// structured data, dumping, verifying and much more. 389254721Semaste//---------------------------------------------------------------------- 390254721Semastevoid 391254721SemasteDWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData) 392254721Semaste{ 393254721Semaste if (dwarf2Data) 394254721Semaste { 395254721Semaste lldb::offset_t offset = 0; 396254721Semaste uint32_t depth = 0; 397254721Semaste DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); 398254721Semaste if (cu.get() == NULL) 399254721Semaste return; 400254721Semaste DWARFDebugInfoEntry die; 401254721Semaste 402254721Semaste while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) 403254721Semaste { 404254721Semaste const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); 405254721Semaste 406254721Semaste depth = 0; 407254721Semaste // Call the callback function with no DIE pointer for the compile unit 408254721Semaste // and get the offset that we are to continue to parse from 409254721Semaste offset = callback(dwarf2Data, cu, NULL, offset, depth, userData); 410254721Semaste 411254721Semaste // Make sure we are within our compile unit 412254721Semaste if (offset < next_cu_offset) 413254721Semaste { 414254721Semaste // We are in our compile unit, parse starting at the offset 415254721Semaste // we were told to parse 416254721Semaste bool done = false; 417254721Semaste while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) 418254721Semaste { 419254721Semaste // Call the callback function with DIE pointer that falls within the compile unit 420254721Semaste offset = callback(dwarf2Data, cu, &die, offset, depth, userData); 421254721Semaste 422254721Semaste if (die.IsNULL()) 423254721Semaste { 424254721Semaste if (depth) 425254721Semaste --depth; 426254721Semaste else 427254721Semaste done = true; // We are done with this compile unit! 428254721Semaste } 429254721Semaste else if (die.HasChildren()) 430254721Semaste ++depth; 431254721Semaste } 432254721Semaste } 433254721Semaste 434254721Semaste // Make sure the offset returned is valid, and if not stop parsing. 435254721Semaste // Returning DW_INVALID_OFFSET from this callback is a good way to end 436254721Semaste // all parsing 437254721Semaste if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) 438254721Semaste break; 439254721Semaste 440254721Semaste // See if during the callback anyone retained a copy of the compile 441254721Semaste // unit other than ourselves and if so, let whomever did own the object 442254721Semaste // and create a new one for our own use! 443254721Semaste if (!cu.unique()) 444254721Semaste cu.reset(new DWARFCompileUnit(dwarf2Data)); 445254721Semaste 446254721Semaste 447254721Semaste // Make sure we start on a proper 448254721Semaste offset = next_cu_offset; 449254721Semaste } 450254721Semaste } 451254721Semaste} 452254721Semaste 453254721Semastetypedef struct DumpInfo 454254721Semaste{ 455254721Semaste DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) : 456254721Semaste strm(init_strm), 457254721Semaste die_offset(off), 458254721Semaste recurse_depth(depth), 459254721Semaste found_depth(UINT32_MAX), 460254721Semaste found_die(false), 461254721Semaste ancestors() 462254721Semaste { 463254721Semaste } 464254721Semaste Stream* strm; 465254721Semaste const uint32_t die_offset; 466254721Semaste const uint32_t recurse_depth; 467254721Semaste uint32_t found_depth; 468254721Semaste bool found_die; 469254721Semaste std::vector<DWARFDebugInfoEntry> ancestors; 470254721Semaste 471254721Semaste DISALLOW_COPY_AND_ASSIGN(DumpInfo); 472254721Semaste} DumpInfo; 473254721Semaste 474254721Semaste//---------------------------------------------------------------------- 475254721Semaste// DumpCallback 476254721Semaste// 477254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function 478254721Semaste// that gets called each time a compile unit header or debug information 479254721Semaste// entry is successfully parsed. 480254721Semaste// 481254721Semaste// This function dump DWARF information and obey recurse depth and 482254721Semaste// whether a single DIE is to be dumped (or all of the data). 483254721Semaste//---------------------------------------------------------------------- 484254721Semastestatic dw_offset_t DumpCallback 485254721Semaste( 486254721Semaste SymbolFileDWARF* dwarf2Data, 487254721Semaste DWARFCompileUnitSP& cu_sp, 488254721Semaste DWARFDebugInfoEntry* die, 489254721Semaste const dw_offset_t next_offset, 490254721Semaste const uint32_t curr_depth, 491254721Semaste void* userData 492254721Semaste) 493254721Semaste{ 494254721Semaste DumpInfo* dumpInfo = (DumpInfo*)userData; 495254721Semaste 496254721Semaste const DWARFCompileUnit* cu = cu_sp.get(); 497254721Semaste 498254721Semaste Stream *s = dumpInfo->strm; 499254721Semaste bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); 500254721Semaste 501254721Semaste if (die) 502254721Semaste { 503254721Semaste // Are we dumping everything? 504254721Semaste if (dumpInfo->die_offset == DW_INVALID_OFFSET) 505254721Semaste { 506254721Semaste // Yes we are dumping everything. Obey our recurse level though 507254721Semaste if (curr_depth < dumpInfo->recurse_depth) 508254721Semaste die->Dump(dwarf2Data, cu, *s, 0); 509254721Semaste } 510254721Semaste else 511254721Semaste { 512254721Semaste // We are dumping a specific DIE entry by offset 513254721Semaste if (dumpInfo->die_offset == die->GetOffset()) 514254721Semaste { 515254721Semaste // We found the DIE we were looking for, dump it! 516254721Semaste if (show_parents) 517254721Semaste { 518254721Semaste s->SetIndentLevel(0); 519254721Semaste const uint32_t num_ancestors = dumpInfo->ancestors.size(); 520254721Semaste if (num_ancestors > 0) 521254721Semaste { 522254721Semaste for (uint32_t i=0; i<num_ancestors-1; ++i) 523254721Semaste { 524254721Semaste dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); 525254721Semaste s->IndentMore(); 526254721Semaste } 527254721Semaste } 528254721Semaste } 529254721Semaste 530254721Semaste dumpInfo->found_depth = curr_depth; 531254721Semaste 532254721Semaste die->Dump(dwarf2Data, cu, *s, 0); 533254721Semaste 534254721Semaste // Note that we found the DIE we were looking for 535254721Semaste dumpInfo->found_die = true; 536254721Semaste 537254721Semaste // Since we are dumping a single DIE, if there are no children we are done! 538254721Semaste if (!die->HasChildren() || dumpInfo->recurse_depth == 0) 539254721Semaste return DW_INVALID_OFFSET; // Return an invalid address to end parsing 540254721Semaste } 541254721Semaste else if (dumpInfo->found_die) 542254721Semaste { 543254721Semaste // Are we done with all the children? 544254721Semaste if (curr_depth <= dumpInfo->found_depth) 545254721Semaste return DW_INVALID_OFFSET; 546254721Semaste 547254721Semaste // We have already found our DIE and are printing it's children. Obey 548254721Semaste // our recurse depth and return an invalid offset if we get done 549254721Semaste // dumping all the the children 550254721Semaste if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) 551254721Semaste die->Dump(dwarf2Data, cu, *s, 0); 552254721Semaste } 553254721Semaste else if (dumpInfo->die_offset > die->GetOffset()) 554254721Semaste { 555254721Semaste if (show_parents) 556254721Semaste dumpInfo->ancestors.back() = *die; 557254721Semaste } 558254721Semaste } 559254721Semaste 560254721Semaste // Keep up with our indent level 561254721Semaste if (die->IsNULL()) 562254721Semaste { 563254721Semaste if (show_parents) 564254721Semaste dumpInfo->ancestors.pop_back(); 565254721Semaste 566254721Semaste if (curr_depth <= 1) 567254721Semaste return cu->GetNextCompileUnitOffset(); 568254721Semaste else 569254721Semaste s->IndentLess(); 570254721Semaste } 571254721Semaste else if (die->HasChildren()) 572254721Semaste { 573254721Semaste if (show_parents) 574254721Semaste { 575254721Semaste DWARFDebugInfoEntry null_die; 576254721Semaste dumpInfo->ancestors.push_back(null_die); 577254721Semaste } 578254721Semaste s->IndentMore(); 579254721Semaste } 580254721Semaste } 581254721Semaste else 582254721Semaste { 583254721Semaste if (cu == NULL) 584254721Semaste s->PutCString("NULL - cu"); 585254721Semaste // We have a compile unit, reset our indent level to zero just in case 586254721Semaste s->SetIndentLevel(0); 587254721Semaste 588254721Semaste // See if we are dumping everything? 589254721Semaste if (dumpInfo->die_offset == DW_INVALID_OFFSET) 590254721Semaste { 591254721Semaste // We are dumping everything 592254721Semaste cu->Dump(s); 593254721Semaste return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit 594254721Semaste } 595254721Semaste else 596254721Semaste { 597254721Semaste if (show_parents) 598254721Semaste { 599254721Semaste dumpInfo->ancestors.clear(); 600254721Semaste dumpInfo->ancestors.resize(1); 601254721Semaste } 602254721Semaste 603254721Semaste // We are dumping only a single DIE possibly with it's children and 604254721Semaste // we must find it's compile unit before we can dump it properly 605254721Semaste if (dumpInfo->die_offset < cu->GetFirstDIEOffset()) 606254721Semaste { 607254721Semaste // Not found, maybe the DIE offset provided wasn't correct? 608254721Semaste // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl; 609254721Semaste return DW_INVALID_OFFSET; 610254721Semaste } 611254721Semaste else 612254721Semaste { 613254721Semaste // See if the DIE is in this compile unit? 614254721Semaste if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) 615254721Semaste { 616254721Semaste // This DIE is in this compile unit! 617254721Semaste if (s->GetVerbose()) 618254721Semaste cu->Dump(s); // Dump the compile unit for the DIE in verbose mode 619254721Semaste 620254721Semaste return next_offset; 621254721Semaste // // We found our compile unit that contains our DIE, just skip to dumping the requested DIE... 622254721Semaste // return dumpInfo->die_offset; 623254721Semaste } 624254721Semaste else 625254721Semaste { 626254721Semaste // Skip to the next compile unit as the DIE isn't in the current one! 627254721Semaste return cu->GetNextCompileUnitOffset(); 628254721Semaste } 629254721Semaste } 630254721Semaste } 631254721Semaste } 632254721Semaste 633254721Semaste // Just return the current offset to parse the next CU or DIE entry 634254721Semaste return next_offset; 635254721Semaste} 636254721Semaste 637254721Semaste//---------------------------------------------------------------------- 638254721Semaste// Dump 639254721Semaste// 640254721Semaste// Dump the information in the .debug_info section to the specified 641254721Semaste// ostream. If die_offset is valid, a single DIE will be dumped. If the 642254721Semaste// die_offset is invalid, all the DWARF information will be dumped. Both 643254721Semaste// cases will obey a "recurse_depth" or how deep to traverse into the 644254721Semaste// children of each DIE entry. A recurse_depth of zero will dump all 645254721Semaste// compile unit headers. A recurse_depth of 1 will dump all compile unit 646254721Semaste// headers and the DW_TAG_compile unit tags. A depth of 2 will also 647254721Semaste// dump all types and functions. 648254721Semaste//---------------------------------------------------------------------- 649254721Semastevoid 650254721SemasteDWARFDebugInfo::Dump 651254721Semaste( 652254721Semaste Stream *s, 653254721Semaste SymbolFileDWARF* dwarf2Data, 654254721Semaste const uint32_t die_offset, 655254721Semaste const uint32_t recurse_depth 656254721Semaste) 657254721Semaste{ 658254721Semaste DumpInfo dumpInfo(s, die_offset, recurse_depth); 659254721Semaste s->PutCString(".debug_info contents"); 660254721Semaste if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) 661254721Semaste { 662254721Semaste if (die_offset == DW_INVALID_OFFSET) 663254721Semaste s->PutCString(":\n"); 664254721Semaste else 665254721Semaste { 666254721Semaste s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset); 667254721Semaste if (recurse_depth != UINT32_MAX) 668254721Semaste s->Printf(" recursing %u levels deep.", recurse_depth); 669254721Semaste s->EOL(); 670254721Semaste } 671254721Semaste } 672254721Semaste else 673254721Semaste { 674254721Semaste s->PutCString(": < EMPTY >\n"); 675254721Semaste return; 676254721Semaste } 677254721Semaste DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo); 678254721Semaste} 679254721Semaste 680254721Semaste 681254721Semaste//---------------------------------------------------------------------- 682254721Semaste// Dump 683254721Semaste// 684254721Semaste// Dump the contents of this DWARFDebugInfo object as has been parsed 685254721Semaste// and/or modified after it has been parsed. 686254721Semaste//---------------------------------------------------------------------- 687254721Semastevoid 688254721SemasteDWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth) 689254721Semaste{ 690254721Semaste DumpInfo dumpInfo(s, die_offset, recurse_depth); 691254721Semaste 692254721Semaste s->PutCString("Dumping .debug_info section from internal representation\n"); 693254721Semaste 694254721Semaste CompileUnitColl::const_iterator pos; 695254721Semaste uint32_t curr_depth = 0; 696254721Semaste ParseCompileUnitHeadersIfNeeded(); 697254721Semaste for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) 698254721Semaste { 699254721Semaste const DWARFCompileUnitSP& cu_sp = *pos; 700254721Semaste DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo); 701254721Semaste 702254721Semaste const DWARFDebugInfoEntry* die = cu_sp->DIE(); 703254721Semaste if (die) 704254721Semaste die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth); 705254721Semaste } 706254721Semaste} 707254721Semaste 708254721Semaste 709254721Semaste//---------------------------------------------------------------------- 710254721Semaste// FindCallbackString 711254721Semaste// 712254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function 713254721Semaste// that gets called each time a compile unit header or debug information 714254721Semaste// entry is successfully parsed. 715254721Semaste// 716254721Semaste// This function will find the die_offset of any items whose DW_AT_name 717254721Semaste// matches the given string 718254721Semaste//---------------------------------------------------------------------- 719254721Semastetypedef struct FindCallbackStringInfoTag 720254721Semaste{ 721254721Semaste const char* name; 722254721Semaste bool ignore_case; 723254721Semaste RegularExpression* regex; 724254721Semaste vector<dw_offset_t>& die_offsets; 725254721Semaste} FindCallbackStringInfo; 726254721Semaste 727254721Semastestatic dw_offset_t FindCallbackString 728254721Semaste( 729254721Semaste SymbolFileDWARF* dwarf2Data, 730254721Semaste DWARFCompileUnitSP& cu_sp, 731254721Semaste DWARFDebugInfoEntry* die, 732254721Semaste const dw_offset_t next_offset, 733254721Semaste const uint32_t curr_depth, 734254721Semaste void* userData 735254721Semaste) 736254721Semaste{ 737254721Semaste FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData; 738254721Semaste const DWARFCompileUnit* cu = cu_sp.get(); 739254721Semaste 740254721Semaste if (die) 741254721Semaste { 742254721Semaste const char* die_name = die->GetName(dwarf2Data, cu); 743254721Semaste if (die_name) 744254721Semaste { 745254721Semaste if (info->regex) 746254721Semaste { 747254721Semaste if (info->regex->Execute(die_name)) 748254721Semaste info->die_offsets.push_back(die->GetOffset()); 749254721Semaste } 750254721Semaste else 751254721Semaste { 752254721Semaste if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0) 753254721Semaste info->die_offsets.push_back(die->GetOffset()); 754254721Semaste } 755254721Semaste } 756254721Semaste } 757254721Semaste 758254721Semaste // Just return the current offset to parse the next CU or DIE entry 759254721Semaste return next_offset; 760254721Semaste} 761254721Semaste 762254721Semaste//---------------------------------------------------------------------- 763254721Semaste// Find 764254721Semaste// 765254721Semaste// Finds all DIE that have a specific DW_AT_name attribute by manually 766254721Semaste// searching through the debug information (not using the 767254721Semaste// .debug_pubnames section). The string must match the entire name 768254721Semaste// and case sensitive searches are an option. 769254721Semaste//---------------------------------------------------------------------- 770254721Semastebool 771254721SemasteDWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const 772254721Semaste{ 773254721Semaste die_offsets.clear(); 774254721Semaste if (name && name[0]) 775254721Semaste { 776254721Semaste FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets }; 777254721Semaste DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 778254721Semaste } 779254721Semaste return !die_offsets.empty(); 780254721Semaste} 781254721Semaste 782254721Semaste//---------------------------------------------------------------------- 783254721Semaste// Find 784254721Semaste// 785254721Semaste// Finds all DIE that have a specific DW_AT_name attribute by manually 786254721Semaste// searching through the debug information (not using the 787254721Semaste// .debug_pubnames section). The string must match the supplied regular 788254721Semaste// expression. 789254721Semaste//---------------------------------------------------------------------- 790254721Semastebool 791254721SemasteDWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const 792254721Semaste{ 793254721Semaste die_offsets.clear(); 794254721Semaste FindCallbackStringInfo info = { NULL, false, &re, die_offsets }; 795254721Semaste DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); 796254721Semaste return !die_offsets.empty(); 797254721Semaste} 798