summaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp300
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);
- }
-}