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