dwarfdump: -summarize-types: print a short summary (unqualified type name, hash, length) of type units rather than dumping contents

This is just a quick utility handy for getting rough summaries of types
in a given object or dwo file. I've been using it to investigate the
amount of type info redundancy across a project build, for example.

llvm-svn: 284537
This commit is contained in:
David Blaikie 2016-10-18 21:09:48 +00:00
parent c0a717ba5b
commit 50cc27ecb9
11 changed files with 70 additions and 41 deletions

View File

@ -144,7 +144,7 @@ public:
virtual ~DIContext() {}
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false) = 0;
bool DumpEH = false, bool SummarizeTypes = false) = 0;
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;

View File

@ -84,7 +84,7 @@ public:
}
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false) override;
bool DumpEH = false, bool SummarizeTypes = false) override;
typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range;
typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;

View File

@ -29,7 +29,7 @@ public:
uint32_t getHeaderSize() const override {
return DWARFUnit::getHeaderSize() + 12;
}
void dump(raw_ostream &OS);
void dump(raw_ostream &OS, bool Brief = false);
static const DWARFSectionKind Section = DW_SECT_TYPES;
protected:

View File

@ -248,7 +248,8 @@ public:
/// unit's DIE vector.
///
/// The unit needs to have its DIEs extracted for this method to work.
const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const {
const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) {
extractDIEsIfNeeded(false);
assert(!DieArray.empty());
auto it = std::lower_bound(
DieArray.begin(), DieArray.end(), Offset,

View File

@ -40,7 +40,7 @@ class COFFObjectFile;
}
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false) override;
bool DumpEH = false, bool SummarizeTypes = false) override;
DILineInfo getLineInfoForAddress(
uint64_t Address,

View File

@ -77,7 +77,8 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
bool SummarizeTypes) {
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
@ -106,7 +107,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
OS << "\n.debug_types contents:\n";
for (const auto &TUS : type_unit_sections())
for (const auto &TU : TUS)
TU->dump(OS);
TU->dump(OS, SummarizeTypes);
}
if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) &&
@ -114,7 +115,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
OS << "\n.debug_types.dwo contents:\n";
for (const auto &DWOTUS : dwo_type_unit_sections())
for (const auto &DWOTU : DWOTUS)
DWOTU->dump(OS);
DWOTU->dump(OS, SummarizeTypes);
}
if (DumpType == DIDT_All || DumpType == DIDT_Loc) {

View File

@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@ -22,7 +24,22 @@ bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
return TypeOffset < getLength();
}
void DWARFTypeUnit::dump(raw_ostream &OS) {
void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) {
const DWARFDebugInfoEntryMinimal *TD =
getDIEForOffset(TypeOffset + getOffset());
DWARFFormValue NameVal;
const char *Name = "";
if (TD->getAttributeValue(this, llvm::dwarf::DW_AT_name, NameVal))
if (auto ON = NameVal.getAsCString(this))
Name = *ON;
if (SummarizeTypes) {
OS << "name = '" << Name << "'"
<< " type_signature = " << format("0x%16" PRIx64, TypeHash)
<< " length = " << format("0x%08x", getLength()) << '\n';
return;
}
OS << format("0x%08x", getOffset()) << ": Type Unit:"
<< " length = " << format("0x%08x", getLength())
<< " version = " << format("0x%04x", getVersion())
@ -30,8 +47,7 @@ void DWARFTypeUnit::dump(raw_ostream &OS) {
<< " addr_size = " << format("0x%02x", getAddressByteSize())
<< " type_signature = " << format("0x%16" PRIx64, TypeHash)
<< " type_offset = " << format("0x%04x", TypeOffset)
<< " (next unit at " << format("0x%08x", getNextUnitOffset())
<< ")\n";
<< " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false))
TU->dump(OS, this, -1U);

View File

@ -29,8 +29,8 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
Session->setLoadAddress(ImageBase.get());
}
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType,
bool DumpEH) {}
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
bool SummarizeTypes) {}
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {

View File

@ -1,32 +1,39 @@
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 > %t
RUN: cat %t | FileCheck -check-prefix=FOO %s
RUN: cat %t | FileCheck -check-prefix=BAR %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck -check-prefix=CHECK -check-prefix=LONG %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 -summarize-types | FileCheck -check-prefix=CHECK -check-prefix=SHORT %s
RUN: llvm-dwarfdump -debug-dump=types %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck -check-prefix=TYPES %s
FOO: debug_info contents:
FOO: DW_TAG_variable
FOO-NEXT: DW_AT_name {{.*}}"f"
FOO: DW_AT_type [DW_FORM_ref_sig8] ([[FOO_SIG:0x[0-9a-f]*]])
CHECK: debug_info contents:
FOO: debug_types contents:
FOO: 0x00000000: Type Unit: {{.*}} type_signature = [[FOO_SIG]] type_offset = 0x[[FOO_OFF:[0-9a-f]*]] (next unit at
FOO: DW_TAG_type_unit
FOO-NOT: NULL
FOO: 0x0000[[FOO_OFF]]: DW_TAG_structure_type
FOO-NEXT: DW_AT_name {{.*}}"foo"
CHECK: DW_TAG_variable
CHECK-NEXT: DW_AT_name {{.*}}"f"
CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[FOO_SIG:0x[0-9a-f]*]])
BAR: debug_info contents:
BAR: DW_TAG_variable
BAR: DW_TAG_variable
BAR-NEXT: DW_AT_name {{.*}}"b"
BAR: DW_AT_type [DW_FORM_ref_sig8] ([[BAR_SIG:0x[0-9a-f]*]])
CHECK: DW_TAG_variable
CHECK-NEXT: DW_AT_name {{.*}}"b"
CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[BAR_SIG:0x[0-9a-f]*]])
BAR: debug_types contents:
BAR: 0x00000000: Type Unit: {{.*}} type_signature = [[BAR_SIG]] type_offset = 0x[[BAR_OFF:[0-9a-f]*]] (next unit at
BAR: DW_TAG_type_unit
BAR-NOT: NULL
BAR: 0x0000[[BAR_OFF]]: DW_TAG_structure_type
BAR-NEXT: DW_AT_name {{.*}}"bar"
CHECK: debug_types contents:
LONG: 0x00000000: Type Unit: {{.*}} name =
SHORT-NOT: Type Unit
SHORT: name =
CHECK-SAME: 'bar' type_signature = [[BAR_SIG]]
SHORT-SAME: length =
LONG-SAME: type_offset = 0x[[BAR_OFF:[0-9a-f]*]] (next unit at
LONG: DW_TAG_type_unit
LONG-NOT: NULL
LONG: 0x0000[[BAR_OFF]]: DW_TAG_structure_type
LONG-NEXT: DW_AT_name {{.*}}"bar"
LONG: 0x00000000: Type Unit: {{.*}} name =
SHORT: name =
CHECK-SAME: 'foo' type_signature = [[FOO_SIG]]
LONG-SAME: type_offset = 0x[[FOO_OFF:[0-9a-f]*]] (next unit at
LONG: DW_TAG_type_unit
LONG-NOT: NULL
LONG: 0x0000[[FOO_OFF]]: DW_TAG_structure_type
LONG-NEXT: DW_AT_name {{.*}}"foo"
TYPES-NOT: debug_info contents:
TYPES: debug_types contents:

View File

@ -19,19 +19,19 @@ b.cpp:
CHECK-LABEL: .debug_types.dwo contents:
CHECK: [[COMMONUOFF:0x[0-9a-f]*]]:
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
CHECK: 0x0000 addr_size = 0x08 type_signature = [[COMMONSIG:0x[0-9a-f]*]] type_offset = 0x[[COMMONOFF:.*]] (next unit at [[AUOFF:.*]])
CHECK: 0x0000 addr_size = 0x08 name = 'common' type_signature = [[COMMONSIG:0x[0-9a-f]*]] type_offset = 0x[[COMMONOFF:.*]] (next unit at [[AUOFF:.*]])
CHECK: DW_TAG_type_unit
CHECK: [[COMMONOFF]]: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "common"
CHECK: [[AUOFF]]:
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
CHECK: 0x0000 addr_size = 0x08 type_signature = [[ASIG:0x[0-9a-f]*]] type_offset = 0x[[AOFF:.*]] (next unit at [[BUOFF:.*]])
CHECK: 0x0000 addr_size = 0x08 name = 'adistinct' type_signature = [[ASIG:0x[0-9a-f]*]] type_offset = 0x[[AOFF:.*]] (next unit at [[BUOFF:.*]])
CHECK: DW_TAG_type_unit
CHECK: 0x00000042: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "adistinct"
CHECK: [[BUOFF]]:
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
CHECK: 0x{{.*}} addr_size = 0x08 type_signature = [[BSIG:0x[0-9a-f]*]] type_offset = 0x[[BOFF:.*]] (next unit at [[XUOFF:.*]])
CHECK: 0x{{.*}} addr_size = 0x08 name = 'bdistinct' type_signature = [[BSIG:0x[0-9a-f]*]] type_offset = 0x[[BOFF:.*]] (next unit at [[XUOFF:.*]])
CHECK: DW_TAG_type_unit
CHECK: 0x00000066: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "bdistinct"

View File

@ -74,6 +74,10 @@ static cl::opt<DIDumpType> DumpType(
clEnumValN(DIDT_GdbIndex, "gdb_index", ".gdb_index"),
clEnumValN(DIDT_TUIndex, "tu_index", ".debug_tu_index")));
static cl::opt<bool>
SummarizeTypes("summarize-types",
cl::desc("Abbreviate the description of type unit entries"));
static void error(StringRef Filename, std::error_code EC) {
if (!EC)
return;
@ -87,7 +91,7 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
// Dump the complete DWARF structure.
DICtx->dump(outs(), DumpType);
DICtx->dump(outs(), DumpType, false, SummarizeTypes);
}
static void DumpInput(StringRef Filename) {