diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
| -rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 300 |
1 files changed, 18 insertions, 282 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 9c0f1d3c89056..dadc30dc918ac 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -72,7 +72,7 @@ DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { bool printed = false; const size_t num_compile_units = GetNumCompileUnits(); for (size_t idx = 0; idx < num_compile_units; ++idx) { - DWARFCompileUnit *cu = GetCompileUnitAtIndex(idx); + DWARFUnit *cu = GetCompileUnitAtIndex(idx); dw_offset_t offset = cu->GetOffset(); if (cus_with_data.find(offset) == cus_with_data.end()) { @@ -97,8 +97,10 @@ void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { if (m_compile_units.empty()) { if (m_dwarf2Data != NULL) { lldb::offset_t offset = 0; - DWARFCompileUnitSP cu_sp; - while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) { + DWARFUnitSP cu_sp; + const auto &debug_info_data = m_dwarf2Data->get_debug_info_data(); + while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data, + &offset))) { m_compile_units.push_back(cu_sp); offset = cu_sp->GetNextCompileUnitOffset(); @@ -112,16 +114,16 @@ size_t DWARFDebugInfo::GetNumCompileUnits() { return m_compile_units.size(); } -DWARFCompileUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) { - DWARFCompileUnit *cu = NULL; +DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) { + DWARFUnit *cu = NULL; if (idx < GetNumCompileUnits()) cu = m_compile_units[idx].get(); return cu; } -bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const { - // Not a verify efficient function, but it is handy for use in assertions - // to make sure that a compile unit comes from a debug information file. +bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const { + // Not a verify efficient function, but it is handy for use in assertions to + // make sure that a compile unit comes from a debug information file. CompileUnitColl::const_iterator end_pos = m_compile_units.end(); CompileUnitColl::const_iterator pos; @@ -133,13 +135,13 @@ bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const { } bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset( - dw_offset_t offset, const DWARFCompileUnitSP &cu_sp) { + dw_offset_t offset, const DWARFUnitSP &cu_sp) { return offset < cu_sp->GetOffset(); } -DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, +DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr) { - DWARFCompileUnitSP cu_sp; + DWARFUnitSP cu_sp; uint32_t cu_idx = DW_INVALID_INDEX; if (cu_offset != DW_INVALID_OFFSET) { ParseCompileUnitHeadersIfNeeded(); @@ -170,18 +172,18 @@ DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, return cu_sp.get(); } -DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) { +DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) { if (die_ref.cu_offset == DW_INVALID_OFFSET) return GetCompileUnitContainingDIEOffset(die_ref.die_offset); else return GetCompileUnit(die_ref.cu_offset); } -DWARFCompileUnit * +DWARFUnit * DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) { ParseCompileUnitHeadersIfNeeded(); - DWARFCompileUnitSP cu_sp; + DWARFUnitSP cu_sp; // Watch out for single compile unit executable as they are pretty common const size_t num_cus = m_compile_units.size(); @@ -205,7 +207,7 @@ DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) { DWARFDIE DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) { - DWARFCompileUnit *cu = GetCompileUnitContainingDIEOffset(die_offset); + DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset); if (cu) return cu->GetDIE(die_offset); return DWARFDIE(); @@ -218,275 +220,9 @@ DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) { //---------------------------------------------------------------------- DWARFDIE DWARFDebugInfo::GetDIE(const DIERef &die_ref) { - DWARFCompileUnit *cu = GetCompileUnit(die_ref); + DWARFUnit *cu = GetCompileUnit(die_ref); if (cu) return cu->GetDIE(die_ref.die_offset); return DWARFDIE(); // Not found } -//---------------------------------------------------------------------- -// Parse -// -// Parses the .debug_info section and uses the .debug_abbrev section -// and various other sections in the SymbolFileDWARF class and calls the -// supplied callback function each time a compile unit header, or debug -// information entry is successfully parsed. This function can be used -// for different tasks such as parsing the file contents into a -// structured data, dumping, verifying and much more. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, - void *userData) { - if (dwarf2Data) { - lldb::offset_t offset = 0; - uint32_t depth = 0; - DWARFDebugInfoEntry die; - - DWARFCompileUnitSP cu; - while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) { - const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); - - depth = 0; - // Call the callback function with no DIE pointer for the compile unit - // and get the offset that we are to continue to parse from - offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData); - - // Make sure we are within our compile unit - if (offset < next_cu_offset) { - // We are in our compile unit, parse starting at the offset - // we were told to parse - bool done = false; - while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) { - // Call the callback function with DIE pointer that falls within the - // compile unit - offset = - callback(dwarf2Data, cu.get(), &die, offset, depth, userData); - - if (die.IsNULL()) { - if (depth) - --depth; - else - done = true; // We are done with this compile unit! - } else if (die.HasChildren()) - ++depth; - } - } - - // Make sure the offset returned is valid, and if not stop parsing. - // Returning DW_INVALID_OFFSET from this callback is a good way to end - // all parsing - if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) - break; - - // Make sure we start on a proper - offset = next_cu_offset; - } - } -} - -typedef struct DumpInfo { - DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth) - : strm(init_strm), die_offset(off), recurse_depth(depth), - found_depth(UINT32_MAX), found_die(false), ancestors() {} - Stream *strm; - const uint32_t die_offset; - const uint32_t recurse_depth; - uint32_t found_depth; - bool found_die; - std::vector<DWARFDebugInfoEntry> ancestors; - - DISALLOW_COPY_AND_ASSIGN(DumpInfo); -} DumpInfo; - -//---------------------------------------------------------------------- -// DumpCallback -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function dump DWARF information and obey recurse depth and -// whether a single DIE is to be dumped (or all of the data). -//---------------------------------------------------------------------- -static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data, - DWARFCompileUnit *cu, DWARFDebugInfoEntry *die, - const dw_offset_t next_offset, - const uint32_t curr_depth, void *userData) { - DumpInfo *dumpInfo = (DumpInfo *)userData; - Stream *s = dumpInfo->strm; - bool show_parents = - s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); - - if (die) { - // Are we dumping everything? - if (dumpInfo->die_offset == DW_INVALID_OFFSET) { - // Yes we are dumping everything. Obey our recurse level though - if (curr_depth < dumpInfo->recurse_depth) - die->Dump(dwarf2Data, cu, *s, 0); - } else { - // We are dumping a specific DIE entry by offset - if (dumpInfo->die_offset == die->GetOffset()) { - // We found the DIE we were looking for, dump it! - if (show_parents) { - s->SetIndentLevel(0); - const uint32_t num_ancestors = dumpInfo->ancestors.size(); - if (num_ancestors > 0) { - for (uint32_t i = 0; i < num_ancestors - 1; ++i) { - dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); - s->IndentMore(); - } - } - } - - dumpInfo->found_depth = curr_depth; - - die->Dump(dwarf2Data, cu, *s, 0); - - // Note that we found the DIE we were looking for - dumpInfo->found_die = true; - - // Since we are dumping a single DIE, if there are no children we are - // done! - if (!die->HasChildren() || dumpInfo->recurse_depth == 0) - return DW_INVALID_OFFSET; // Return an invalid address to end parsing - } else if (dumpInfo->found_die) { - // Are we done with all the children? - if (curr_depth <= dumpInfo->found_depth) - return DW_INVALID_OFFSET; - - // We have already found our DIE and are printing it's children. Obey - // our recurse depth and return an invalid offset if we get done - // dumping all of the children - if (dumpInfo->recurse_depth == UINT32_MAX || - curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) - die->Dump(dwarf2Data, cu, *s, 0); - } else if (dumpInfo->die_offset > die->GetOffset()) { - if (show_parents) - dumpInfo->ancestors.back() = *die; - } - } - - // Keep up with our indent level - if (die->IsNULL()) { - if (show_parents) - dumpInfo->ancestors.pop_back(); - - if (curr_depth <= 1) - return cu->GetNextCompileUnitOffset(); - else - s->IndentLess(); - } else if (die->HasChildren()) { - if (show_parents) { - DWARFDebugInfoEntry null_die; - dumpInfo->ancestors.push_back(null_die); - } - s->IndentMore(); - } - } else { - if (cu == NULL) - s->PutCString("NULL - cu"); - // We have a compile unit, reset our indent level to zero just in case - s->SetIndentLevel(0); - - // See if we are dumping everything? - if (dumpInfo->die_offset == DW_INVALID_OFFSET) { - // We are dumping everything - if (cu) { - cu->Dump(s); - return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this - // Compile Unit - } else { - return DW_INVALID_OFFSET; - } - } else { - if (show_parents) { - dumpInfo->ancestors.clear(); - dumpInfo->ancestors.resize(1); - } - - // We are dumping only a single DIE possibly with it's children and - // we must find it's compile unit before we can dump it properly - if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) { - // Not found, maybe the DIE offset provided wasn't correct? - // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " - // was not found." << endl; - return DW_INVALID_OFFSET; - } else { - // See if the DIE is in this compile unit? - if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) { - return next_offset; - // // We found our compile unit that contains our DIE, just skip to - // dumping the requested DIE... - // return dumpInfo->die_offset; - } else { - // Skip to the next compile unit as the DIE isn't in the current one! - if (cu) { - return cu->GetNextCompileUnitOffset(); - } else { - return DW_INVALID_OFFSET; - } - } - } - } - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - -//---------------------------------------------------------------------- -// Dump -// -// Dump the information in the .debug_info section to the specified -// ostream. If die_offset is valid, a single DIE will be dumped. If the -// die_offset is invalid, all the DWARF information will be dumped. Both -// cases will obey a "recurse_depth" or how deep to traverse into the -// children of each DIE entry. A recurse_depth of zero will dump all -// compile unit headers. A recurse_depth of 1 will dump all compile unit -// headers and the DW_TAG_compile unit tags. A depth of 2 will also -// dump all types and functions. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data, - const uint32_t die_offset, - const uint32_t recurse_depth) { - DumpInfo dumpInfo(s, die_offset, recurse_depth); - s->PutCString(".debug_info contents"); - if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) { - if (die_offset == DW_INVALID_OFFSET) - s->PutCString(":\n"); - else { - s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset); - if (recurse_depth != UINT32_MAX) - s->Printf(" recursing %u levels deep.", recurse_depth); - s->EOL(); - } - } else { - s->PutCString(": < EMPTY >\n"); - return; - } - DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo); -} - -//---------------------------------------------------------------------- -// Dump -// -// Dump the contents of this DWARFDebugInfo object as has been parsed -// and/or modified after it has been parsed. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset, - const uint32_t recurse_depth) { - DumpInfo dumpInfo(s, die_offset, recurse_depth); - - s->PutCString("Dumping .debug_info section from internal representation\n"); - - CompileUnitColl::const_iterator pos; - uint32_t curr_depth = 0; - ParseCompileUnitHeadersIfNeeded(); - for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) { - DWARFCompileUnit *cu = pos->get(); - DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo); - - const DWARFDIE die = cu->DIE(); - if (die) - die.Dump(s, recurse_depth); - } -} |
