forked from OSchip/llvm-project
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:
parent
c0a717ba5b
commit
50cc27ecb9
|
@ -144,7 +144,7 @@ public:
|
||||||
virtual ~DIContext() {}
|
virtual ~DIContext() {}
|
||||||
|
|
||||||
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
|
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,
|
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
|
||||||
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
|
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
|
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<DWARFCompileUnit>::iterator_range cu_iterator_range;
|
||||||
typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
|
typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
uint32_t getHeaderSize() const override {
|
uint32_t getHeaderSize() const override {
|
||||||
return DWARFUnit::getHeaderSize() + 12;
|
return DWARFUnit::getHeaderSize() + 12;
|
||||||
}
|
}
|
||||||
void dump(raw_ostream &OS);
|
void dump(raw_ostream &OS, bool Brief = false);
|
||||||
static const DWARFSectionKind Section = DW_SECT_TYPES;
|
static const DWARFSectionKind Section = DW_SECT_TYPES;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -248,7 +248,8 @@ public:
|
||||||
/// unit's DIE vector.
|
/// unit's DIE vector.
|
||||||
///
|
///
|
||||||
/// The unit needs to have its DIEs extracted for this method to work.
|
/// 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());
|
assert(!DieArray.empty());
|
||||||
auto it = std::lower_bound(
|
auto it = std::lower_bound(
|
||||||
DieArray.begin(), DieArray.end(), Offset,
|
DieArray.begin(), DieArray.end(), Offset,
|
||||||
|
|
|
@ -40,7 +40,7 @@ class COFFObjectFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
|
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
|
||||||
bool DumpEH = false) override;
|
bool DumpEH = false, bool SummarizeTypes = false) override;
|
||||||
|
|
||||||
DILineInfo getLineInfoForAddress(
|
DILineInfo getLineInfoForAddress(
|
||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
|
|
|
@ -77,7 +77,8 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
|
||||||
Accel.dump(OS);
|
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) {
|
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
|
||||||
OS << ".debug_abbrev contents:\n";
|
OS << ".debug_abbrev contents:\n";
|
||||||
getDebugAbbrev()->dump(OS);
|
getDebugAbbrev()->dump(OS);
|
||||||
|
@ -106,7 +107,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
|
||||||
OS << "\n.debug_types contents:\n";
|
OS << "\n.debug_types contents:\n";
|
||||||
for (const auto &TUS : type_unit_sections())
|
for (const auto &TUS : type_unit_sections())
|
||||||
for (const auto &TU : TUS)
|
for (const auto &TU : TUS)
|
||||||
TU->dump(OS);
|
TU->dump(OS, SummarizeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) &&
|
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";
|
OS << "\n.debug_types.dwo contents:\n";
|
||||||
for (const auto &DWOTUS : dwo_type_unit_sections())
|
for (const auto &DWOTUS : dwo_type_unit_sections())
|
||||||
for (const auto &DWOTU : DWOTUS)
|
for (const auto &DWOTU : DWOTUS)
|
||||||
DWOTU->dump(OS);
|
DWOTU->dump(OS, SummarizeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
|
if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
|
#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/Format.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
@ -22,7 +24,22 @@ bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
|
||||||
return TypeOffset < getLength();
|
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:"
|
OS << format("0x%08x", getOffset()) << ": Type Unit:"
|
||||||
<< " length = " << format("0x%08x", getLength())
|
<< " length = " << format("0x%08x", getLength())
|
||||||
<< " version = " << format("0x%04x", getVersion())
|
<< " version = " << format("0x%04x", getVersion())
|
||||||
|
@ -30,8 +47,7 @@ void DWARFTypeUnit::dump(raw_ostream &OS) {
|
||||||
<< " addr_size = " << format("0x%02x", getAddressByteSize())
|
<< " addr_size = " << format("0x%02x", getAddressByteSize())
|
||||||
<< " type_signature = " << format("0x%16" PRIx64, TypeHash)
|
<< " type_signature = " << format("0x%16" PRIx64, TypeHash)
|
||||||
<< " type_offset = " << format("0x%04x", TypeOffset)
|
<< " type_offset = " << format("0x%04x", TypeOffset)
|
||||||
<< " (next unit at " << format("0x%08x", getNextUnitOffset())
|
<< " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
|
||||||
<< ")\n";
|
|
||||||
|
|
||||||
if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false))
|
if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false))
|
||||||
TU->dump(OS, this, -1U);
|
TU->dump(OS, this, -1U);
|
||||||
|
|
|
@ -29,8 +29,8 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
|
||||||
Session->setLoadAddress(ImageBase.get());
|
Session->setLoadAddress(ImageBase.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType,
|
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
|
||||||
bool DumpEH) {}
|
bool SummarizeTypes) {}
|
||||||
|
|
||||||
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
|
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
|
||||||
DILineInfoSpecifier Specifier) {
|
DILineInfoSpecifier Specifier) {
|
||||||
|
|
|
@ -1,32 +1,39 @@
|
||||||
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 > %t
|
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck -check-prefix=CHECK -check-prefix=LONG %s
|
||||||
RUN: cat %t | FileCheck -check-prefix=FOO %s
|
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 -summarize-types | FileCheck -check-prefix=CHECK -check-prefix=SHORT %s
|
||||||
RUN: cat %t | FileCheck -check-prefix=BAR %s
|
|
||||||
RUN: llvm-dwarfdump -debug-dump=types %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck -check-prefix=TYPES %s
|
RUN: llvm-dwarfdump -debug-dump=types %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck -check-prefix=TYPES %s
|
||||||
|
|
||||||
FOO: debug_info contents:
|
CHECK: 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]*]])
|
|
||||||
|
|
||||||
FOO: debug_types contents:
|
CHECK: DW_TAG_variable
|
||||||
FOO: 0x00000000: Type Unit: {{.*}} type_signature = [[FOO_SIG]] type_offset = 0x[[FOO_OFF:[0-9a-f]*]] (next unit at
|
CHECK-NEXT: DW_AT_name {{.*}}"f"
|
||||||
FOO: DW_TAG_type_unit
|
CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[FOO_SIG:0x[0-9a-f]*]])
|
||||||
FOO-NOT: NULL
|
|
||||||
FOO: 0x0000[[FOO_OFF]]: DW_TAG_structure_type
|
|
||||||
FOO-NEXT: DW_AT_name {{.*}}"foo"
|
|
||||||
|
|
||||||
BAR: debug_info contents:
|
CHECK: DW_TAG_variable
|
||||||
BAR: DW_TAG_variable
|
CHECK-NEXT: DW_AT_name {{.*}}"b"
|
||||||
BAR: DW_TAG_variable
|
CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[BAR_SIG:0x[0-9a-f]*]])
|
||||||
BAR-NEXT: DW_AT_name {{.*}}"b"
|
|
||||||
BAR: 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
|
CHECK: debug_types contents:
|
||||||
BAR: DW_TAG_type_unit
|
|
||||||
BAR-NOT: NULL
|
LONG: 0x00000000: Type Unit: {{.*}} name =
|
||||||
BAR: 0x0000[[BAR_OFF]]: DW_TAG_structure_type
|
SHORT-NOT: Type Unit
|
||||||
BAR-NEXT: DW_AT_name {{.*}}"bar"
|
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-NOT: debug_info contents:
|
||||||
TYPES: debug_types contents:
|
TYPES: debug_types contents:
|
||||||
|
|
|
@ -19,19 +19,19 @@ b.cpp:
|
||||||
CHECK-LABEL: .debug_types.dwo contents:
|
CHECK-LABEL: .debug_types.dwo contents:
|
||||||
CHECK: [[COMMONUOFF:0x[0-9a-f]*]]:
|
CHECK: [[COMMONUOFF:0x[0-9a-f]*]]:
|
||||||
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
|
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: DW_TAG_type_unit
|
||||||
CHECK: [[COMMONOFF]]: DW_TAG_structure_type
|
CHECK: [[COMMONOFF]]: DW_TAG_structure_type
|
||||||
CHECK: DW_AT_name {{.*}} "common"
|
CHECK: DW_AT_name {{.*}} "common"
|
||||||
CHECK: [[AUOFF]]:
|
CHECK: [[AUOFF]]:
|
||||||
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
|
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: DW_TAG_type_unit
|
||||||
CHECK: 0x00000042: DW_TAG_structure_type
|
CHECK: 0x00000042: DW_TAG_structure_type
|
||||||
CHECK: DW_AT_name {{.*}} "adistinct"
|
CHECK: DW_AT_name {{.*}} "adistinct"
|
||||||
CHECK: [[BUOFF]]:
|
CHECK: [[BUOFF]]:
|
||||||
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
|
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: DW_TAG_type_unit
|
||||||
CHECK: 0x00000066: DW_TAG_structure_type
|
CHECK: 0x00000066: DW_TAG_structure_type
|
||||||
CHECK: DW_AT_name {{.*}} "bdistinct"
|
CHECK: DW_AT_name {{.*}} "bdistinct"
|
||||||
|
|
|
@ -74,6 +74,10 @@ static cl::opt<DIDumpType> DumpType(
|
||||||
clEnumValN(DIDT_GdbIndex, "gdb_index", ".gdb_index"),
|
clEnumValN(DIDT_GdbIndex, "gdb_index", ".gdb_index"),
|
||||||
clEnumValN(DIDT_TUIndex, "tu_index", ".debug_tu_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) {
|
static void error(StringRef Filename, std::error_code EC) {
|
||||||
if (!EC)
|
if (!EC)
|
||||||
return;
|
return;
|
||||||
|
@ -87,7 +91,7 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
|
||||||
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
|
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
|
||||||
<< "\n\n";
|
<< "\n\n";
|
||||||
// Dump the complete DWARF structure.
|
// Dump the complete DWARF structure.
|
||||||
DICtx->dump(outs(), DumpType);
|
DICtx->dump(outs(), DumpType, false, SummarizeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DumpInput(StringRef Filename) {
|
static void DumpInput(StringRef Filename) {
|
||||||
|
|
Loading…
Reference in New Issue