forked from OSchip/llvm-project
llvm-dwarfdump: implement --recurse-depth=<N>
This patch implements the Darwin dwarfdump option --recurse-depth=<N>, which limits the recursion depth when selectively printing DIEs at an offset. Differential Revision: https://reviews.llvm.org/D38064 llvm-svn: 313778
This commit is contained in:
parent
8b250344e9
commit
d3f9f2138d
|
@ -138,10 +138,26 @@ enum DIDumpType : unsigned {
|
|||
/// dumped.
|
||||
struct DIDumpOptions {
|
||||
unsigned DumpType = DIDT_All;
|
||||
unsigned RecurseDepth = -1U;
|
||||
bool ShowChildren = false;
|
||||
bool ShowParents = false;
|
||||
bool SummarizeTypes = false;
|
||||
bool Verbose = false;
|
||||
|
||||
/// Return default option set for printing a single DIE without children.
|
||||
static DIDumpOptions getForSingleDIE() {
|
||||
DIDumpOptions Opts;
|
||||
Opts.RecurseDepth = 0;
|
||||
return Opts;
|
||||
}
|
||||
|
||||
/// Return the options with RecurseDepth set to 0 unless explicitly required.
|
||||
DIDumpOptions noImplicitRecursion() const {
|
||||
DIDumpOptions Opts = *this;
|
||||
if (RecurseDepth == -1U && !ShowChildren)
|
||||
Opts.RecurseDepth = 0;
|
||||
return Opts;
|
||||
}
|
||||
};
|
||||
|
||||
class DIContext {
|
||||
|
|
|
@ -117,10 +117,8 @@ public:
|
|||
/// Dump the DIE and all of its attributes to the supplied stream.
|
||||
///
|
||||
/// \param OS the stream to use for output.
|
||||
/// \param recurseDepth the depth to recurse to when dumping this DIE and its
|
||||
/// children.
|
||||
/// \param indent the number of characters to indent each line that is output.
|
||||
void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0,
|
||||
void dump(raw_ostream &OS, unsigned indent = 0,
|
||||
DIDumpOptions DumpOpts = DIDumpOptions()) const;
|
||||
|
||||
|
||||
|
|
|
@ -215,7 +215,8 @@ private:
|
|||
DataExtractor *StrData, const char *SectionName);
|
||||
|
||||
public:
|
||||
DWARFVerifier(raw_ostream &S, DWARFContext &D, DIDumpOptions DumpOpts = {})
|
||||
DWARFVerifier(raw_ostream &S, DWARFContext &D,
|
||||
DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE())
|
||||
: OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {}
|
||||
/// Verify the information in any of the following sections, if available:
|
||||
/// .debug_abbrev, debug_abbrev.dwo
|
||||
|
|
|
@ -27,7 +27,7 @@ void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
|
|||
<< ")\n";
|
||||
|
||||
if (DWARFDie CUDie = getUnitDIE(false))
|
||||
CUDie.dump(OS, -1U, 0, DumpOpts);
|
||||
CUDie.dump(OS, 0, DumpOpts);
|
||||
else
|
||||
OS << "<compile unit can't be parsed!>\n\n";
|
||||
}
|
||||
|
|
|
@ -258,7 +258,8 @@ void DWARFContext::dump(
|
|||
DWARFSection Section, cu_iterator_range CUs) {
|
||||
if (shouldDump(IsExplicit, Name, DIDT_ID_DebugInfo, Section.Data)) {
|
||||
if (DumpOffset)
|
||||
getDIEForOffset(DumpOffset.getValue()).dump(OS, 0, 0, DumpOpts);
|
||||
getDIEForOffset(DumpOffset.getValue())
|
||||
.dump(OS, 0, DumpOpts.noImplicitRecursion());
|
||||
else
|
||||
for (const auto &CU : CUs)
|
||||
CU->dump(OS, DumpOpts);
|
||||
|
@ -276,7 +277,8 @@ void DWARFContext::dump(
|
|||
for (const auto &TUS : TUSections)
|
||||
for (const auto &TU : TUS)
|
||||
if (DumpOffset)
|
||||
TU->getDIEForOffset(*DumpOffset).dump(OS, 0, 0, DumpOpts);
|
||||
TU->getDIEForOffset(*DumpOffset)
|
||||
.dump(OS, 0, DumpOpts.noImplicitRecursion());
|
||||
else
|
||||
TU->dump(OS, DumpOpts);
|
||||
};
|
||||
|
|
|
@ -373,19 +373,19 @@ static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,
|
|||
if (!Die)
|
||||
return Indent;
|
||||
Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts);
|
||||
Die.dump(OS, 0, Indent, DumpOpts);
|
||||
Die.dump(OS, Indent, DumpOpts);
|
||||
return Indent + 2;
|
||||
}
|
||||
|
||||
void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent,
|
||||
void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
|
||||
DIDumpOptions DumpOpts) const {
|
||||
if (!isValid())
|
||||
return;
|
||||
DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
|
||||
const uint32_t Offset = getOffset();
|
||||
uint32_t offset = Offset;
|
||||
if (DumpOpts.ShowChildren)
|
||||
RecurseDepth++;
|
||||
// if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth)
|
||||
// DumpOpts.RecurseDepth++;
|
||||
if (DumpOpts.ShowParents) {
|
||||
DumpOpts.ShowParents = false;
|
||||
Indent = dumpParentChain(getParent(), OS, Indent, DumpOpts);
|
||||
|
@ -423,9 +423,10 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent,
|
|||
}
|
||||
|
||||
DWARFDie child = getFirstChild();
|
||||
if (RecurseDepth > 0 && child) {
|
||||
if (DumpOpts.RecurseDepth > 0 && child) {
|
||||
DumpOpts.RecurseDepth--;
|
||||
while (child) {
|
||||
child.dump(OS, RecurseDepth-1, Indent+2, DumpOpts);
|
||||
child.dump(OS, Indent+2, DumpOpts);
|
||||
child = child.getSibling();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ void DWARFTypeUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
|
|||
<< " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
|
||||
|
||||
if (DWARFDie TU = getUnitDIE(false))
|
||||
TU.dump(OS, -1U, 0, DumpOpts);
|
||||
TU.dump(OS, 0, DumpOpts);
|
||||
else
|
||||
OS << "<type unit can't be parsed!>\n\n";
|
||||
}
|
||||
|
|
|
@ -369,13 +369,13 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
|
|||
++NumErrors;
|
||||
OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
|
||||
"bounds:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
} else {
|
||||
++NumErrors;
|
||||
OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
break;
|
||||
|
@ -387,13 +387,13 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
|
|||
OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
|
||||
"bounds: "
|
||||
<< format("0x%08" PRIx64, *SectionOffset) << "\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
} else {
|
||||
++NumErrors;
|
||||
OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
break;
|
||||
|
@ -428,7 +428,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
|
|||
<< format("0x%08" PRIx64, CUOffset)
|
||||
<< " is invalid (must be less than CU size of "
|
||||
<< format("0x%08" PRIx32, CUSize) << "):\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
} else {
|
||||
// Valid reference, but we will verify it points to an actual
|
||||
|
@ -448,7 +448,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
|
|||
++NumErrors;
|
||||
OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
|
||||
"bounds:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
} else {
|
||||
// Valid reference, but we will verify it points to an actual
|
||||
|
@ -464,7 +464,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
|
|||
if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
|
||||
++NumErrors;
|
||||
OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
break;
|
||||
|
@ -489,7 +489,7 @@ unsigned DWARFVerifier::verifyDebugInfoReferences() {
|
|||
<< ". Offset is in between DIEs:\n";
|
||||
for (auto Offset : Pair.second) {
|
||||
auto ReferencingDie = DCtx.getDIEForOffset(Offset);
|
||||
ReferencingDie.dump(OS, 0, 0, DumpOpts);
|
||||
ReferencingDie.dump(OS, 0, DumpOpts);
|
||||
OS << "\n";
|
||||
}
|
||||
OS << "\n";
|
||||
|
@ -514,7 +514,7 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() {
|
|||
++NumDebugLineErrors;
|
||||
OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
|
||||
<< "] was not able to be parsed for CU:\n";
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << '\n';
|
||||
continue;
|
||||
}
|
||||
|
@ -532,8 +532,8 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() {
|
|||
<< format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
|
||||
<< format("0x%08" PRIx32, Die.getOffset())
|
||||
<< ", have the same DW_AT_stmt_list section offset:\n";
|
||||
Iter->second.dump(OS, 0, 0, DumpOpts);
|
||||
Die.dump(OS, 0, 0, DumpOpts);
|
||||
Iter->second.dump(OS, 0, DumpOpts);
|
||||
Die.dump(OS, 0, DumpOpts);
|
||||
OS << '\n';
|
||||
// Already verified this line table before, no need to do it again.
|
||||
continue;
|
||||
|
|
|
@ -21,6 +21,22 @@ CHILDREN: .debug_info contents:
|
|||
CHILDREN: 0x0000000b: DW_TAG_compile_unit
|
||||
CHILDREN: DW_TAG_subprogram
|
||||
|
||||
RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
|
||||
RUN: | llvm-dwarfdump -debug-info=0x0000000b -c -r 0 - \
|
||||
RUN: | FileCheck %s
|
||||
|
||||
RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
|
||||
RUN: | llvm-dwarfdump -debug-info=0x0000000b -c -r 1 - \
|
||||
RUN: | FileCheck %s --check-prefix=CHILDREN
|
||||
|
||||
RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
|
||||
RUN: | llvm-dwarfdump -debug-info=0x0000000b -c -recurse-depth 0 - \
|
||||
RUN: | FileCheck %s
|
||||
|
||||
RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
|
||||
RUN: | llvm-dwarfdump -debug-info=0x0000000b -c -recurse-depth 1 - \
|
||||
RUN: | FileCheck %s --check-prefix=CHILDREN
|
||||
|
||||
RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
|
||||
RUN: | llvm-dwarfdump -debug-info=0x00000043 --show-parents - \
|
||||
RUN: | FileCheck %s --check-prefix=PARENTS
|
||||
|
|
|
@ -15,3 +15,16 @@ CHILDREN: .debug_types contents:
|
|||
CHILDREN: 0x00000017: DW_TAG_type_unit
|
||||
CHILDREN: 0x00000019: DW_TAG_structure_type
|
||||
CHECK-NOT: {{:}}
|
||||
|
||||
RUN: llvm-mc %p/Inputs/typeunit-header.s -filetype obj \
|
||||
RUN: -triple x86_64-unknown-elf -o - \
|
||||
RUN: | llvm-dwarfdump -c -r 0 -debug-types=0x0000017 - \
|
||||
RUN: | FileCheck %s --check-prefix=ZERO-CHILDREN
|
||||
ZERO-CHILDREN: .debug_types contents:
|
||||
ZERO-CHILDREN: 0x00000017: DW_TAG_type_unit
|
||||
ZERO-CHILDREN-NOT: DW_TAG_
|
||||
|
||||
RUN: llvm-mc %p/Inputs/typeunit-header.s -filetype obj \
|
||||
RUN: -triple x86_64-unknown-elf -o - \
|
||||
RUN: | llvm-dwarfdump -c -r 1 -debug-types=0x0000017 - \
|
||||
RUN: | FileCheck %s --check-prefix=CHILDREN
|
||||
|
|
|
@ -5,6 +5,7 @@ HELP-NOT: -reverse-iterate
|
|||
HELP: Section-specific Dump Options
|
||||
HELP: -debug-info - Dump the .debug_info section
|
||||
HELP: -eh-frame
|
||||
HELP: -recurse-depth=<N>
|
||||
HELP: -show-children
|
||||
HELP: -show-parents
|
||||
HELP: -summarize-types
|
||||
|
|
|
@ -1744,10 +1744,11 @@ void DwarfLinker::reportWarning(const Twine &Warning,
|
|||
return;
|
||||
|
||||
DIDumpOptions DumpOpts;
|
||||
DumpOpts.RecurseDepth = 0;
|
||||
DumpOpts.Verbose = Options.Verbose;
|
||||
|
||||
errs() << " in DIE:\n";
|
||||
DIE->dump(errs(), 0 /* RecurseDepth */, 6 /* Indent */, DumpOpts);
|
||||
DIE->dump(errs(), 6 /* Indent */, DumpOpts);
|
||||
}
|
||||
|
||||
bool DwarfLinker::createStreamer(const Triple &TheTriple,
|
||||
|
@ -2112,8 +2113,9 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
|
|||
|
||||
if (Options.Verbose) {
|
||||
DIDumpOptions DumpOpts;
|
||||
DumpOpts.RecurseDepth = 0;
|
||||
DumpOpts.Verbose = Options.Verbose;
|
||||
DIE.dump(outs(), 0, 8 /* Indent */, DumpOpts);
|
||||
DIE.dump(outs(), 8 /* Indent */, DumpOpts);
|
||||
}
|
||||
|
||||
return Flags | TF_Keep;
|
||||
|
@ -2147,8 +2149,9 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
|||
|
||||
if (Options.Verbose) {
|
||||
DIDumpOptions DumpOpts;
|
||||
DumpOpts.RecurseDepth = 0;
|
||||
DumpOpts.Verbose = Options.Verbose;
|
||||
DIE.dump(outs(), 0, 8 /* Indent */, DumpOpts);
|
||||
DIE.dump(outs(), 8 /* Indent */, DumpOpts);
|
||||
}
|
||||
|
||||
Flags |= TF_Keep;
|
||||
|
@ -3486,8 +3489,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
|||
if (Options.Verbose) {
|
||||
outs() << "Input compilation unit:";
|
||||
DIDumpOptions DumpOpts;
|
||||
DumpOpts.RecurseDepth = 0;
|
||||
DumpOpts.Verbose = Options.Verbose;
|
||||
CUDie.dump(outs(), 0, 0, DumpOpts);
|
||||
CUDie.dump(outs(), 0, DumpOpts);
|
||||
}
|
||||
|
||||
if (!registerModuleReference(CUDie, *CU, ModuleMap)) {
|
||||
|
|
|
@ -144,6 +144,13 @@ static opt<bool>
|
|||
cat(DwarfDumpCategory));
|
||||
static alias ShowParentsAlias("p", desc("Alias for -show-parents"),
|
||||
aliasopt(ShowParents));
|
||||
static opt<unsigned> RecurseDepth(
|
||||
"recurse-depth",
|
||||
desc("Only recurse to a depth of N when displaying debug info entries."),
|
||||
cat(DwarfDumpCategory), init(-1U), value_desc("N"));
|
||||
static alias RecurseDepthAlias("r", desc("Alias for -recurse-depth"),
|
||||
aliasopt(RecurseDepth));
|
||||
|
||||
static opt<bool>
|
||||
SummarizeTypes("summarize-types",
|
||||
desc("Abbreviate the description of type unit entries"),
|
||||
|
@ -172,10 +179,14 @@ static void error(StringRef Filename, std::error_code EC) {
|
|||
static DIDumpOptions getDumpOpts() {
|
||||
DIDumpOptions DumpOpts;
|
||||
DumpOpts.DumpType = DumpType;
|
||||
DumpOpts.RecurseDepth = RecurseDepth;
|
||||
DumpOpts.ShowChildren = ShowChildren;
|
||||
DumpOpts.ShowParents = ShowParents;
|
||||
DumpOpts.SummarizeTypes = SummarizeTypes;
|
||||
DumpOpts.Verbose = Verbose;
|
||||
// In -verify mode, print DIEs without children in error messages.
|
||||
if (Verify)
|
||||
return DumpOpts.noImplicitRecursion();
|
||||
return DumpOpts;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue