From 25bdef70ce566da3b7b205f9fa7308585f4f106b 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 --- include/llvm/DebugInfo/DIContext.h | 16 ++++++++++++++ include/llvm/DebugInfo/DWARF/DWARFDie.h | 4 +--- include/llvm/DebugInfo/DWARF/DWARFVerifier.h | 3 ++- lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 2 +- lib/DebugInfo/DWARF/DWARFContext.cpp | 6 +++-- lib/DebugInfo/DWARF/DWARFDie.cpp | 13 ++++++----- lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 2 +- lib/DebugInfo/DWARF/DWARFVerifier.cpp | 22 +++++++++---------- .../llvm-dwarfdump/X86/debug_info_offset.test | 16 ++++++++++++++ .../llvm-dwarfdump/X86/debug_type_offset.test | 13 +++++++++++ test/tools/llvm-dwarfdump/cmdline.test | 1 + tools/dsymutil/DwarfLinker.cpp | 12 ++++++---- tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 11 ++++++++++ 13 files changed, 92 insertions(+), 29 deletions(-) diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 12093fed12f..881b997df05 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/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/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index 9ae43958c89..9cb067a0129 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/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/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index bbb603f943d..b4add789b1f 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/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/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 358e9bf43d0..43b235621d1 100644 --- a/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/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/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 0e28954f5c1..f20a7ca024b 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/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/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index f588f2599c2..31074a81a98 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/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/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index 67cc0505e18..206c12fa403 100644 --- a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/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/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 24a0e67b003..096d5ff8c33 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/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/test/tools/llvm-dwarfdump/X86/debug_info_offset.test b/test/tools/llvm-dwarfdump/X86/debug_info_offset.test index 59c8c7c7b45..cd9032c1d2b 100644 --- a/test/tools/llvm-dwarfdump/X86/debug_info_offset.test +++ b/test/tools/llvm-dwarfdump/X86/debug_info_offset.test @@ -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 diff --git a/test/tools/llvm-dwarfdump/X86/debug_type_offset.test b/test/tools/llvm-dwarfdump/X86/debug_type_offset.test index 6fd36e619dc..492e5e54ed9 100644 --- a/test/tools/llvm-dwarfdump/X86/debug_type_offset.test +++ b/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/test/tools/llvm-dwarfdump/cmdline.test b/test/tools/llvm-dwarfdump/cmdline.test index be1be6bbdb1..0e31d7129a6 100644 --- a/test/tools/llvm-dwarfdump/cmdline.test +++ b/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/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index b91b80ea08e..3ab3c7f5720 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/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/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 61d77aa76f4..aba59d0d5b9 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/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; }