From d3f9f2138d953025cf46720138ee41dd567e5b4d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 20 Sep 2017 17:44:00 +0000 Subject: [PATCH] llvm-dwarfdump: implement --recurse-depth= This patch implements the Darwin dwarfdump option --recurse-depth=, which limits the recursion depth when selectively printing DIEs at an offset. Differential Revision: https://reviews.llvm.org/D38064 llvm-svn: 313778 --- llvm/include/llvm/DebugInfo/DIContext.h | 16 ++++++++++++++++ llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 4 +--- llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h | 3 ++- llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 2 +- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 6 ++++-- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 13 +++++++------ llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 2 +- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 22 +++++++++++----------- .../llvm-dwarfdump/X86/debug_info_offset.test | 16 ++++++++++++++++ .../llvm-dwarfdump/X86/debug_type_offset.test | 13 +++++++++++++ llvm/test/tools/llvm-dwarfdump/cmdline.test | 1 + llvm/tools/dsymutil/DwarfLinker.cpp | 12 ++++++++---- llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 11 +++++++++++ 13 files changed, 92 insertions(+), 29 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h index 12093fe..881b997 100644 --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -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 { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index 9ae4395..9cb067a 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -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; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index bbb603f..b4add78 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -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 diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 358e9bf..43b2356 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -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 << "\n\n"; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 0e28954..f20a7ca 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -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); }; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index f588f25..31074a8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -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(); } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index 67cc050..206c12f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -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 << "\n\n"; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 24a0e67..096d5ff 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -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; diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test index 59c8c7c..cd9032c 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test @@ -22,6 +22,22 @@ 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 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_type_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_type_offset.test index 6fd36e6..492e5e5 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_type_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_type_offset.test @@ -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 diff --git a/llvm/test/tools/llvm-dwarfdump/cmdline.test b/llvm/test/tools/llvm-dwarfdump/cmdline.test index be1be6b..0e31d71 100644 --- a/llvm/test/tools/llvm-dwarfdump/cmdline.test +++ b/llvm/test/tools/llvm-dwarfdump/cmdline.test @@ -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= HELP: -show-children HELP: -show-parents HELP: -summarize-types diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index b91b80e..3ab3c7f 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -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)) { diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 61d77aa..aba59d0 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -144,6 +144,13 @@ static opt cat(DwarfDumpCategory)); static alias ShowParentsAlias("p", desc("Alias for -show-parents"), aliasopt(ShowParents)); +static opt 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 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; } -- 2.7.4