Index: llvm/trunk/include/llvm/DebugInfo/DIContext.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DIContext.h +++ llvm/trunk/include/llvm/DebugInfo/DIContext.h @@ -138,10 +138,26 @@ /// 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 { Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -117,10 +117,8 @@ /// 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; Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -215,7 +215,8 @@ 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 Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -27,7 +27,7 @@ << ")\n"; if (DWARFDie CUDie = getUnitDIE(false)) - CUDie.dump(OS, -1U, 0, DumpOpts); + CUDie.dump(OS, 0, DumpOpts); else OS << "\n\n"; } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -258,7 +258,8 @@ 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 @@ 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); }; Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -373,19 +373,19 @@ 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 @@ } 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(); } } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -55,7 +55,7 @@ << " (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"; } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -369,13 +369,13 @@ ++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 @@ 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 @@ << 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 @@ ++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 @@ 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 @@ << ". 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 @@ ++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 @@ << 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; Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test @@ -22,6 +22,22 @@ 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 Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_type_offset.test =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_type_offset.test +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_type_offset.test @@ -15,3 +15,16 @@ 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 Index: llvm/trunk/test/tools/llvm-dwarfdump/cmdline.test =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/cmdline.test +++ llvm/trunk/test/tools/llvm-dwarfdump/cmdline.test @@ -5,6 +5,7 @@ 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 Index: llvm/trunk/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp @@ -1744,10 +1744,11 @@ 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 @@ 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 @@ 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 @@ 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)) { Index: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -144,6 +144,13 @@ 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 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; }