Add command-line flags for DWARF dumping.

Flags for dumping specific DWARF sections added in lib/DebugInfo and
llvm-dwarfdump.

llvm-svn: 173480
This commit is contained in:
Eli Bendersky 2013-01-25 20:26:43 +00:00
parent a19fa86a70
commit 7a94daa170
5 changed files with 131 additions and 65 deletions

View File

@ -92,6 +92,22 @@ public:
}
};
/// Selects which debug sections get dumped.
enum DIDumpType {
DIDT_Null,
DIDT_All,
DIDT_Abbrev,
DIDT_AbbrevDwo,
DIDT_Aranges,
DIDT_Info,
DIDT_InfoDwo,
DIDT_Line,
DIDT_Ranges,
DIDT_Str,
DIDT_StrDwo,
DIDT_StrOffsetsDwo
};
// In place of applying the relocations to the data we've read from disk we use
// a separate mapping table to the side and checking that at locations in the
// dwarf where we expect relocated values. This adds a bit of complexity to the
@ -106,7 +122,7 @@ public:
/// getDWARFContext - get a context for binary DWARF data.
static DIContext *getDWARFContext(object::ObjectFile *);
virtual void dump(raw_ostream &OS) = 0;
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0;
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;

View File

@ -19,80 +19,100 @@ using namespace dwarf;
typedef DWARFDebugLine::LineTable DWARFLineTable;
void DWARFContext::dump(raw_ostream &OS) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
}
OS << "\n.debug_info contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
getCompileUnitAtIndex(i)->dump(OS);
if (DumpType == DIDT_All || DumpType == DIDT_Info) {
OS << "\n.debug_info contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
getCompileUnitAtIndex(i)->dump(OS);
}
OS << "\n.debug_aranges contents:\n";
DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
uint32_t offset = 0;
DWARFDebugArangeSet set;
while (set.extract(arangesData, &offset))
set.dump(OS);
if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
OS << "\n.debug_aranges contents:\n";
DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
DWARFDebugArangeSet set;
while (set.extract(arangesData, &offset))
set.dump(OS);
}
uint8_t savedAddressByteSize = 0;
OS << "\n.debug_line contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
savedAddressByteSize = cu->getAddressByteSize();
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-1U);
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection(), isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
if (DumpType == DIDT_All || DumpType == DIDT_Line) {
OS << "\n.debug_line contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
savedAddressByteSize = cu->getAddressByteSize();
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-1U);
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection(), isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
}
}
}
OS << "\n.debug_str contents:\n";
DataExtractor strData(getStringSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) {
OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
strOffset = offset;
if (DumpType == DIDT_All || DumpType == DIDT_Str) {
OS << "\n.debug_str contents:\n";
DataExtractor strData(getStringSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) {
OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
strOffset = offset;
}
}
OS << "\n.debug_ranges contents:\n";
// In fact, different compile units may have different address byte
// sizes, but for simplicity we just use the address byte size of the last
// compile unit (there is no easy and fast way to associate address range
// list and the compile unit it describes).
DataExtractor rangesData(getRangeSection(), isLittleEndian(),
savedAddressByteSize);
offset = 0;
DWARFDebugRangeList rangeList;
while (rangeList.extract(rangesData, &offset))
rangeList.dump(OS);
OS << "\n.debug_abbrev.dwo contents:\n";
getDebugAbbrevDWO()->dump(OS);
OS << "\n.debug_info.dwo contents:\n";
for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
getDWOCompileUnitAtIndex(i)->dump(OS);
OS << "\n.debug_str.dwo contents:\n";
DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strDWOOffset = 0;
while (const char *s = strDWOData.getCStr(&offset)) {
OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
strDWOOffset = offset;
if (DumpType == DIDT_All || DumpType == DIDT_Ranges) {
OS << "\n.debug_ranges contents:\n";
// In fact, different compile units may have different address byte
// sizes, but for simplicity we just use the address byte size of the last
// compile unit (there is no easy and fast way to associate address range
// list and the compile unit it describes).
DataExtractor rangesData(getRangeSection(), isLittleEndian(),
savedAddressByteSize);
offset = 0;
DWARFDebugRangeList rangeList;
while (rangeList.extract(rangesData, &offset))
rangeList.dump(OS);
}
OS << "\n.debug_str_offsets.dwo contents:\n";
DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
offset = 0;
while (offset < getStringOffsetDWOSection().size()) {
OS << format("0x%8.8x: ", offset);
OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
OS << "\n.debug_abbrev.dwo contents:\n";
getDebugAbbrevDWO()->dump(OS);
}
if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) {
OS << "\n.debug_info.dwo contents:\n";
for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
getDWOCompileUnitAtIndex(i)->dump(OS);
}
if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) {
OS << "\n.debug_str.dwo contents:\n";
DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strDWOOffset = 0;
while (const char *s = strDWOData.getCStr(&offset)) {
OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
strDWOOffset = offset;
}
}
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
OS << "\n.debug_str_offsets.dwo contents:\n";
DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
offset = 0;
while (offset < getStringOffsetDWOSection().size()) {
OS << format("0x%8.8x: ", offset);
OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
}
}
}

View File

@ -45,7 +45,7 @@ class DWARFContext : public DIContext {
public:
DWARFContext() {}
virtual void dump(raw_ostream &OS);
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All);
/// Get the number of compile units in this context.
unsigned getNumCompileUnits() {

View File

@ -0,0 +1,13 @@
; RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test.elf-x86-64 -debug-dump=all | FileCheck %s -check-prefix DUMP_ALL
; RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test.elf-x86-64 -debug-dump=info | FileCheck %s -check-prefix DUMP_INFO
; RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test.elf-x86-64 -debug-dump=ranges | FileCheck %s -check-prefix DUMP_RANGES
; DUMP_ALL: .debug_info
; DUMP_ALL: .debug_ranges
; DUMP_INFO: .debug_info
; DUMP_INFO-NOT: .debug_ranges
; DUMP_RANGES-NOT: .debug_info
; DUMP_RANGES: .debug_ranges

View File

@ -52,6 +52,23 @@ static cl::opt<bool>
PrintInlining("inlining", cl::init(false),
cl::desc("Print all inlined frames for a given address"));
static cl::opt<DIDumpType>
DumpType("debug-dump", cl::init(DIDT_All),
cl::desc("Dump of debug sections:"),
cl::values(
clEnumValN(DIDT_All, "all", "Dump all debug sections"),
clEnumValN(DIDT_Abbrev, "abbrev", ".debug_abbrev"),
clEnumValN(DIDT_AbbrevDwo, "abbrev.dwo", ".debug_abbrev.dwo"),
clEnumValN(DIDT_Aranges, "aranges", ".debug_aranges"),
clEnumValN(DIDT_Info, "info", ".debug_info"),
clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
clEnumValN(DIDT_Line, "line", ".debug_line"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Str, "str", ".debug_str"),
clEnumValN(DIDT_StrDwo, "str.dwo", ".debug_str.dwo"),
clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo", ".debug_str_offsets.dwo"),
clEnumValEnd));
static void PrintDILineInfo(DILineInfo dli) {
if (PrintFunctions)
outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>")
@ -75,7 +92,7 @@ static void DumpInput(const StringRef &Filename) {
outs() << Filename
<< ":\tfile format " << Obj->getFileFormatName() << "\n\n";
// Dump the complete DWARF structure.
DICtx->dump(outs());
DICtx->dump(outs(), DumpType);
} else {
// Print line info for the specified address.
int SpecFlags = DILineInfoSpecifier::FileLineInfo |