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

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 15 16:04:05 PDT 2017


Author: adrian
Date: Fri Sep 15 16:04:04 2017
New Revision: 313419

URL: http://llvm.org/viewvc/llvm-project?rev=313419&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.

This reapplies r313412 with some extra qualification to appease GCC and MSVC.

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=313419&r1=313418&r2=313419&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DIContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DIContext.h Fri Sep 15 16:04:04 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=313419&r1=313418&r2=313419&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h Fri Sep 15 16:04:04 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=313419&r1=313418&r2=313419&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Fri Sep 15 16:04:04 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=313419&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 16:04:04 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=313419&r1=313418&r2=313419&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Fri Sep 15 16:04:04 2017
@@ -37,8 +37,63 @@
 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;
+};
+
+namespace llvm {
+namespace cl {
+template <>
+class parser<OffsetOption> final : public 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 {};
+};
+} // cl
+} // llvm
+
+/// @}
+/// 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 +102,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<llvm::Optional<uint64_t>, (unsigned)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 +139,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 +167,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 +301,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