summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2017-09-15 22:37:56 +0000
committerAdrian Prantl <aprantl@apple.com>2017-09-15 22:37:56 +0000
commitfb5d284e976ed39bd1a0a7d7032a5e77adb2c60e (patch)
treef58c583c42b66c46f58bcd645042f28c47e6db1b
parentad66fefdca18eeb9966d1a0cd426da4a6262765e (diff)
downloadbcm5719-llvm-fb5d284e976ed39bd1a0a7d7032a5e77adb2c60e.tar.gz
bcm5719-llvm-fb5d284e976ed39bd1a0a7d7032a5e77adb2c60e.zip
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. llvm-svn: 313412
-rw-r--r--llvm/include/llvm/DebugInfo/DIContext.h5
-rw-r--r--llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h10
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp98
-rw-r--r--llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test10
-rw-r--r--llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp83
5 files changed, 147 insertions, 59 deletions
diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h
index c7429069873..59f8e297296 100644
--- a/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/llvm/include/llvm/DebugInfo/DIContext.h
@@ -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
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index a89d883ee0b..e43a9ba8adf 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -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;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index c9832f43c24..3914b5a441a 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -216,7 +216,11 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
}
}
-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, DIDumpOptions DumpOpts) {
// 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, DIDumpOptions DumpOpts) {
}
}
- 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, DIDumpOptions DumpOpts) {
}
}
- 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, DIDumpOptions DumpOpts) {
}
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, DIDumpOptions DumpOpts) {
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, DIDumpOptions DumpOpts) {
}
}
- 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, DIDumpOptions DumpOpts) {
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, DIDumpOptions DumpOpts) {
}
}
- 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, DIDumpOptions DumpOpts) {
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());
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test
new file mode 100644
index 00000000000..d3d1b6a94c6
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_info_offset.test
@@ -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
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 823eb8e8133..7671bd8adaf 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -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 &Obj, Twine Filename) {
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)
OpenPOWER on IntegriCloud