[llvm] r313412 - llvm-dwarfdump: Add support for -debug-info=<offset>.

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 15 15:37:56 PDT 2017


Author: adrian
Date: Fri Sep 15 15:37:56 2017
New Revision: 313412

URL: http://llvm.org/viewvc/llvm-project?rev=313412&view=rev
Log:
llvm-dwarfdump: Add support for -debug-info=<offset>.

This is the first of many commits that enable selectively dumping just
one record from the debug info.

Added:
    llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/DIContext.h
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DIContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DIContext.h?rev=313412&r1=313411&r2=313412&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DIContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DIContext.h Fri Sep 15 15:37:56 2017
@@ -114,7 +114,6 @@ struct DILineInfoSpecifier {
 
 /// This is just a helper to programmatically construct DIDumpType.
 enum DIDumpTypeCounter {
-  DIDT_ID_Null = 0,
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
   DIDT_ID_##ENUM_NAME,
 #include "llvm/BinaryFormat/Dwarf.def"
@@ -129,10 +128,10 @@ enum DIDumpType : unsigned {
   DIDT_Null,
   DIDT_All             = ~0U,
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
-  DIDT_##ENUM_NAME = 1U << (DIDT_ID_##ENUM_NAME - 1),
+  DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
 #include "llvm/BinaryFormat/Dwarf.def"
 #undef HANDLE_DWARF_SECTION
-  DIDT_UUID = 1 << (DIDT_ID_UUID - 1),
+  DIDT_UUID = 1 << DIDT_ID_UUID,
 };
 
 /// Container for dump options that control which debug information will be

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h?rev=313412&r1=313411&r2=313412&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h Fri Sep 15 15:37:56 2017
@@ -121,7 +121,15 @@ public:
     return DICtx->getKind() == CK_DWARF;
   }
 
-  void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override;
+  /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
+  /// dump only the record at the specified offset.
+  void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+            std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
+
+  void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
+    std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
+    dump(OS, DumpOpts, DumpOffsets);
+  }
 
   bool verify(raw_ostream &OS, unsigned DumpType = DIDT_All,
               DIDumpOptions DumpOpts = {}) override;

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=313412&r1=313411&r2=313412&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Fri Sep 15 15:37:56 2017
@@ -216,7 +216,11 @@ static void dumpStringOffsetsSection(raw
   }
 }
 
-void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
+void DWARFContext::dump(
+    raw_ostream &OS, DIDumpOptions DumpOpts,
+    std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
+
+  Optional<uint64_t> DumpOffset;
   uint64_t DumpType = DumpOpts.DumpType;
   bool DumpEH = DumpOpts.DumpEH;
 
@@ -230,37 +234,41 @@ void DWARFContext::dump(raw_ostream &OS,
 
   // Print a header for each explicitly-requested section.
   // Otherwise just print one for non-empty sections.
+  // Only print empty .dwo section headers when dumping a .dwo file.
   bool Explicit = DumpType != DIDT_All && !IsDWO;
-  auto shouldDump = [&](bool IsExplicit, const char *Name,
-                        unsigned DIDT_Section, StringRef Section) {
-    bool Should = (DumpType & DIDT_Section) && (IsExplicit || !Section.empty());
+  bool ExplicitDWO = Explicit && IsDWO;
+  auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
+                        StringRef Section) {
+    DumpOffset = DumpOffsets[ID];
+    unsigned Mask = 1U << ID;
+    bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
     if (Should)
-      OS << '\n' << Name << " contents:\n";
+      OS << "\n" << Name << " contents:\n";
     return Should;
   };
-  // Only print empty .dwo section headers when dumping a .dwo file.
-  bool ExplicitDWO = Explicit && IsDWO;
 
   // Dump individual sections.
-  if (shouldDump(Explicit, ".debug_abbrev", DIDT_DebugAbbrev,
-                 DObj->getAbbrevSection())) {
+  if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
+                 DObj->getAbbrevSection()))
     getDebugAbbrev()->dump(OS);
-  }
-  if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_DebugAbbrev,
-                 DObj->getAbbrevDWOSection())) {
+  if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
+                 DObj->getAbbrevDWOSection()))
     getDebugAbbrevDWO()->dump(OS);
-  }
 
-  if (shouldDump(Explicit, ".debug_info", DIDT_DebugInfo,
-                 DObj->getInfoSection().Data)) {
-    for (const auto &CU : compile_units())
-      CU->dump(OS, DumpOpts);
-  }
-  if (shouldDump(ExplicitDWO, ".debug_info.dwo", DIDT_DebugInfo,
-                 DObj->getInfoDWOSection().Data)) {
-    for (const auto &DWOCU : dwo_compile_units())
-      DWOCU->dump(OS, DumpOpts);
-  }
+  auto dumpDebugInfo = [&](bool IsExplicit, const char *Name,
+                           DWARFSection Section, cu_iterator_range CUs) {
+    if (shouldDump(IsExplicit, Name, DIDT_ID_DebugInfo, Section.Data)) {
+      for (const auto &CU : CUs)
+        if (DumpOffset)
+        CU->getDIEForOffset(DumpOffset.getValue()).dump(OS, 0);
+        else
+          CU->dump(OS, DumpOpts);
+    }
+  };
+  dumpDebugInfo(Explicit, ".debug_info", DObj->getInfoSection(),
+                compile_units());
+  dumpDebugInfo(ExplicitDWO, ".debug_info.dwo", DObj->getInfoDWOSection(),
+                dwo_compile_units());
 
   if ((DumpType & DIDT_DebugTypes)) {
     if (Explicit || getNumTypeUnits()) {
@@ -277,16 +285,16 @@ void DWARFContext::dump(raw_ostream &OS,
     }
   }
 
-  if (shouldDump(Explicit, ".debug_loc", DIDT_DebugLoc,
+  if (shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
                  DObj->getLocSection().Data)) {
     getDebugLoc()->dump(OS, getRegisterInfo());
   }
-  if (shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_DebugLoc,
+  if (shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
                  DObj->getLocDWOSection().Data)) {
     getDebugLocDWO()->dump(OS, getRegisterInfo());
   }
 
-  if (shouldDump(Explicit, ".debug_frame", DIDT_DebugFrames,
+  if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrames,
                  DObj->getDebugFrameSection())) {
     getDebugFrame()->dump(OS);
   }
@@ -302,7 +310,7 @@ void DWARFContext::dump(raw_ostream &OS,
     }
   }
 
-  if (shouldDump(Explicit, ".debug_aranges", DIDT_DebugAranges,
+  if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
                  DObj->getARangeSection())) {
     uint32_t offset = 0;
     DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0);
@@ -312,7 +320,7 @@ void DWARFContext::dump(raw_ostream &OS,
   }
 
   uint8_t savedAddressByteSize = 0;
-  if (shouldDump(Explicit, ".debug_line", DIDT_DebugLine,
+  if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
                  DObj->getLineSection().Data)) {
     for (const auto &CU : compile_units()) {
       savedAddressByteSize = CU->getAddressByteSize();
@@ -335,7 +343,7 @@ void DWARFContext::dump(raw_ostream &OS,
     savedAddressByteSize = CU->getAddressByteSize();
     break;
   }
-  if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_DebugLine,
+  if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
                  DObj->getLineDWOSection().Data)) {
     unsigned stmtOffset = 0;
     DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(),
@@ -347,17 +355,17 @@ void DWARFContext::dump(raw_ostream &OS,
     }
   }
 
-  if (shouldDump(Explicit, ".debug_cu_index", DIDT_DebugCUIndex,
+  if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
                  DObj->getCUIndexSection())) {
     getCUIndex().dump(OS);
   }
 
-  if (shouldDump(Explicit, ".debug_tu_index", DIDT_DebugTUIndex,
+  if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
                  DObj->getTUIndexSection())) {
     getTUIndex().dump(OS);
   }
 
-  if (shouldDump(Explicit, ".debug_str", DIDT_DebugStr,
+  if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
                  DObj->getStringSection())) {
     DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0);
     uint32_t offset = 0;
@@ -367,7 +375,7 @@ void DWARFContext::dump(raw_ostream &OS,
       strOffset = offset;
     }
   }
-  if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_DebugStr,
+  if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
                  DObj->getStringDWOSection())) {
     DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0);
     uint32_t offset = 0;
@@ -378,7 +386,7 @@ void DWARFContext::dump(raw_ostream &OS,
     }
   }
 
-  if (shouldDump(Explicit, ".debug_ranges", DIDT_DebugRanges,
+  if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
                  DObj->getRangeSection().Data)) {
     // In fact, different compile units may have different address byte
     // sizes, but for simplicity we just use the address byte size of the
@@ -393,60 +401,60 @@ void DWARFContext::dump(raw_ostream &OS,
       rangeList.dump(OS);
   }
 
-  if (shouldDump(Explicit, ".debug_pubnames", DIDT_DebugPubnames,
+  if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
                  DObj->getPubNamesSection()))
     DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false)
         .dump(OS);
 
-  if (shouldDump(Explicit, ".debug_pubtypes", DIDT_DebugPubtypes,
+  if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
                  DObj->getPubTypesSection()))
     DWARFDebugPubTable(DObj->getPubTypesSection(), isLittleEndian(), false)
         .dump(OS);
 
-  if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_DebugGnuPubnames,
+  if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
                  DObj->getGnuPubNamesSection()))
     DWARFDebugPubTable(DObj->getGnuPubNamesSection(), isLittleEndian(),
                        true /* GnuStyle */)
         .dump(OS);
 
-  if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_DebugGnuPubtypes,
+  if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
                  DObj->getGnuPubTypesSection()))
     DWARFDebugPubTable(DObj->getGnuPubTypesSection(), isLittleEndian(),
                        true /* GnuStyle */)
         .dump(OS);
 
-  if (shouldDump(Explicit, ".debug_str_offsets", DIDT_DebugStrOffsets,
+  if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
                  DObj->getStringOffsetSection().Data))
     dumpStringOffsetsSection(
         OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(),
         DObj->getStringSection(), isLittleEndian(), getMaxVersion());
-  if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_DebugStrOffsets,
+  if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
                  DObj->getStringOffsetDWOSection().Data))
     dumpStringOffsetsSection(
         OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(),
         DObj->getStringDWOSection(), isLittleEndian(), getMaxVersion());
 
-  if (shouldDump(Explicit, ".gnu_index", DIDT_GdbIndex,
+  if (shouldDump(Explicit, ".gnu_index", DIDT_ID_GdbIndex,
                  DObj->getGdbIndexSection())) {
     getGdbIndex().dump(OS);
   }
 
-  if (shouldDump(Explicit, ".apple_names", DIDT_AppleNames,
+  if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
                  DObj->getAppleNamesSection().Data))
     dumpAccelSection(OS, *DObj, DObj->getAppleNamesSection(),
                      DObj->getStringSection(), isLittleEndian());
 
-  if (shouldDump(Explicit, ".apple_types", DIDT_AppleTypes,
+  if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
                  DObj->getAppleTypesSection().Data))
     dumpAccelSection(OS, *DObj, DObj->getAppleTypesSection(),
                      DObj->getStringSection(), isLittleEndian());
 
-  if (shouldDump(Explicit, ".apple_namespaces", DIDT_AppleNamespaces,
+  if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
                  DObj->getAppleNamespacesSection().Data))
     dumpAccelSection(OS, *DObj, DObj->getAppleNamespacesSection(),
                      DObj->getStringSection(), isLittleEndian());
 
-  if (shouldDump(Explicit, ".apple_objc", DIDT_AppleObjC,
+  if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
                  DObj->getAppleObjCSection().Data))
     dumpAccelSection(OS, *DObj, DObj->getAppleObjCSection(),
                      DObj->getStringSection(), isLittleEndian());

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test?rev=313412&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug_info_offset.test Fri Sep 15 15:37:56 2017
@@ -0,0 +1,10 @@
+RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
+RUN:   | llvm-dwarfdump -debug-info=0x0000000b - | FileCheck %s
+CHECK: .debug_info contents:
+CHECK: 0x0000000b: DW_TAG_compile_unit
+CHECK:               DW_AT_name
+CHECK-NOT: {{:}}
+
+RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
+RUN:   | llvm-dwarfdump -debug-info=0 - | FileCheck --allow-empty --check-prefix=EMPTY %s
+EMPTY-NOT: DW_TAG

Modified: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp?rev=313412&r1=313411&r2=313412&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Fri Sep 15 15:37:56 2017
@@ -37,8 +37,59 @@
 using namespace llvm;
 using namespace object;
 
+/// Parser for options that take an optional offest argument.
+/// @{
+struct OffsetOption {
+  uint64_t Val = 0;
+  bool HasValue = false;
+  bool IsRequested = false;
+};
+
+template <>
+class cl::parser<OffsetOption> final : public cl::basic_parser<OffsetOption> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  /// Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, OffsetOption &Val) {
+    if (Arg == "") {
+      Val.Val = 0;
+      Val.HasValue = false;
+      Val.IsRequested = true;
+      return false;
+    }
+    if (Arg.getAsInteger(0, Val.Val))
+      return O.error("'" + Arg + "' value invalid for integer argument!");
+    Val.HasValue = true;
+    Val.IsRequested = true;
+    return false;
+  }
+
+  enum ValueExpected getValueExpectedFlagDefault() const {
+    return ValueOptional;
+  }
+
+  void printOptionInfo(const Option &O, size_t GlobalWidth) const {
+    outs() << "  -" << O.ArgStr;
+    Option::printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O));
+  }
+
+  void printOptionDiff(const Option &O, OffsetOption V, OptVal Default,
+                       size_t GlobalWidth) const {
+    printOptionName(O, GlobalWidth);
+    outs() << "[=offset]";
+  }
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override {};
+};
+
+/// @}
+/// Command line options.
+/// @{
+
 namespace {
-using namespace llvm::cl;
+using namespace cl;
 
 OptionCategory DwarfDumpCategory("Specific Options");
 static opt<bool> Help("h", desc("Alias for -help"), Hidden,
@@ -47,20 +98,26 @@ static list<std::string>
     InputFilenames(Positional, desc("<input object files or .dSYM bundles>"),
                    ZeroOrMore, cat(DwarfDumpCategory));
 
-cl::OptionCategory
-    SectionCategory("Section-specific Dump Options",
-                    "These control which sections are dumped.");
+cl::OptionCategory SectionCategory("Section-specific Dump Options",
+                                   "These control which sections are dumped. "
+                                   "Where applicable these parameters take an "
+                                   "optional =<offset> argument to dump only "
+                                   "the entry at the specified offset.");
+
 static opt<bool> DumpAll("all", desc("Dump all debug info sections"),
                          cat(SectionCategory));
 static alias DumpAllAlias("a", desc("Alias for -all"), aliasopt(DumpAll));
 
+// Options for dumping specific sections.
 static unsigned DumpType = DIDT_Null;
+static std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME)                \
-  static opt<bool> Dump##ENUM_NAME(CMDLINE_NAME,                               \
-                                   desc("Dump the " ELF_NAME " section"),      \
-                                   cat(SectionCategory));
+  static opt<OffsetOption> Dump##ENUM_NAME(                                    \
+      CMDLINE_NAME, desc("Dump the " ELF_NAME " section"),                     \
+      cat(SectionCategory));
 #include "llvm/BinaryFormat/Dwarf.def"
 #undef HANDLE_DWARF_SECTION
+
 static opt<bool> DumpUUID("uuid", desc("Show the UUID for each architecture"),
                           cat(DwarfDumpCategory));
 static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID));
@@ -78,6 +135,9 @@ static opt<bool> Verbose("verbose",
 static alias VerboseAlias("v", desc("Alias for -verbose"), aliasopt(Verbose),
                           cat(DwarfDumpCategory));
 } // namespace
+/// @}
+//===----------------------------------------------------------------------===//
+
 
 static void error(StringRef Filename, std::error_code EC) {
   if (!EC)
@@ -103,7 +163,7 @@ static bool dumpObjectFile(ObjectFile &O
     outs() << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n';
 
   // Dump the complete DWARF structure.
-  DICtx->dump(outs(), getDumpOpts());
+  DICtx->dump(outs(), getDumpOpts(), DumpOffsets);
   return true;
 }
 
@@ -237,8 +297,11 @@ int main(int argc, char **argv) {
   // Defaults to dumping all sections, unless brief mode is specified in which
   // case only the .debug_info section in dumped.
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME)                \
-  if (Dump##ENUM_NAME)                                                         \
-    DumpType |= DIDT_##ENUM_NAME;
+  if (Dump##ENUM_NAME.IsRequested) {                                           \
+    DumpType |= DIDT_##ENUM_NAME;                                              \
+    if (Dump##ENUM_NAME.HasValue)                                              \
+      DumpOffsets[DIDT_ID_##ENUM_NAME] = Dump##ENUM_NAME.Val;                  \
+  }
 #include "llvm/BinaryFormat/Dwarf.def"
 #undef HANDLE_DWARF_SECTION
   if (DumpUUID)




More information about the llvm-commits mailing list