llvm.org GIT mirror llvm / e26d793
Reapply "[dwarfdump] Add support for dumping accelerator tables." This reverts commit r221842 which was a revert of r221836 and of the test parts of r221837. This new version fixes an UB bug pointed out by David (along with addressing some other review comments), makes some dumping more resilient to broken input data and forces the accelerator tables to be dumped in the tests where we use them (this decision is platform specific otherwise). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222003 91177308-0d34-0410-b5e6-96231b3b80d8 Frederic Riss 6 years ago
10 changed file(s) with 285 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
106106 DIDT_GnuPubtypes,
107107 DIDT_Str,
108108 DIDT_StrDwo,
109 DIDT_StrOffsetsDwo
109 DIDT_StrOffsetsDwo,
110 DIDT_AppleNames,
111 DIDT_AppleTypes,
112 DIDT_AppleNamespaces,
113 DIDT_AppleObjC
110114 };
111115
112116 // In place of applying the relocations to the data we've read from disk we use
0 add_llvm_library(LLVMDebugInfo
11 DIContext.cpp
22 DWARFAbbreviationDeclaration.cpp
3 DWARFAcceleratorTable.cpp
34 DWARFCompileUnit.cpp
45 DWARFContext.cpp
56 DWARFDebugAbbrev.cpp
0 #include "DWARFAcceleratorTable.h"
1
2 #include "llvm/Support/Dwarf.h"
3 #include "llvm/Support/Format.h"
4 #include "llvm/Support/raw_ostream.h"
5
6 namespace llvm {
7
8 bool DWARFAcceleratorTable::extract() {
9 uint32_t Offset = 0;
10
11 // Check that we can at least read the header.
12 if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4))
13 return false;
14
15 Hdr.Magic = AccelSection.getU32(&Offset);
16 Hdr.Version = AccelSection.getU16(&Offset);
17 Hdr.HashFunction = AccelSection.getU16(&Offset);
18 Hdr.NumBuckets = AccelSection.getU32(&Offset);
19 Hdr.NumHashes = AccelSection.getU32(&Offset);
20 Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
21
22 // Check that we can read all the hashes and offsets from the
23 // section (see SourceLevelDebugging.rst for the structure of the index).
24 if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
25 Hdr.NumBuckets*4 + Hdr.NumHashes*8))
26 return false;
27
28 HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
29 uint32_t NumAtoms = AccelSection.getU32(&Offset);
30
31 for (unsigned i = 0; i < NumAtoms; ++i) {
32 uint16_t AtomType = AccelSection.getU16(&Offset);
33 DWARFFormValue AtomForm(AccelSection.getU16(&Offset));
34 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
35 }
36
37 return true;
38 }
39
40 void DWARFAcceleratorTable::dump(raw_ostream &OS) {
41 // Dump the header.
42 OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
43 << "Version = " << format("0x%04x", Hdr.Version) << '\n'
44 << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n'
45 << "Bucket count = " << Hdr.NumBuckets << '\n'
46 << "Hashes count = " << Hdr.NumHashes << '\n'
47 << "HeaderData length = " << Hdr.HeaderDataLength << '\n'
48 << "DIE offset base = " << HdrData.DIEOffsetBase << '\n'
49 << "Number of atoms = " << HdrData.Atoms.size() << '\n';
50
51 unsigned i = 0;
52 for (const auto &Atom: HdrData.Atoms) {
53 OS << format("Atom[%d] Type: ", i++);
54 if (const char *TypeString = dwarf::AtomTypeString(Atom.first))
55 OS << TypeString;
56 else
57 OS << format("DW_ATOM_Unknown_0x%x", Atom.first);
58 OS << " Form: ";
59 if (const char *FormString = dwarf::FormEncodingString(Atom.second.getForm()))
60 OS << FormString;
61 else
62 OS << format("DW_FORM_Unknown_0x%x", Atom.second.getForm());
63 OS << '\n';
64 }
65
66 // Now go through the actual tables and dump them.
67 uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
68 unsigned HashesBase = Offset + Hdr.NumBuckets * 4;
69 unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;
70
71 for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) {
72 unsigned Index = AccelSection.getU32(&Offset);
73
74 OS << format("Bucket[%d]\n", Bucket);
75 if (Index == UINT32_MAX) {
76 OS << " EMPTY\n";
77 continue;
78 }
79
80 for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) {
81 unsigned HashOffset = HashesBase + HashIdx*4;
82 unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
83 uint32_t Hash = AccelSection.getU32(&HashOffset);
84
85 if (Hash % Hdr.NumBuckets != Bucket)
86 break;
87
88 unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
89 OS << format(" Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset);
90 if (!AccelSection.isValidOffset(DataOffset)) {
91 OS << " Invalid section offset\n";
92 continue;
93 }
94 while (unsigned StringOffset = AccelSection.getU32(&DataOffset)) {
95 OS << format(" Name: %08x \"%s\"\n", StringOffset,
96 StringSection.getCStr(&StringOffset));
97 unsigned NumData = AccelSection.getU32(&DataOffset);
98 for (unsigned Data = 0; Data < NumData; ++Data) {
99 OS << format(" Data[%d] => ", Data);
100 unsigned i = 0;
101 for (auto &Atom : HdrData.Atoms) {
102 OS << format("{Atom[%d]: ", i++);
103 if (Atom.second.extractValue(AccelSection, &DataOffset, nullptr))
104 Atom.second.dump(OS, nullptr);
105 else
106 OS << "Error extracting the value";
107 OS << "} ";
108 }
109 OS << '\n';
110 }
111 }
112 }
113 }
114 }
115 }
0
1 #include "llvm/ADT/SmallVector.h"
2 #include "llvm/DebugInfo/DWARFFormValue.h"
3
4 #include
5
6 namespace llvm {
7
8 class DWARFAcceleratorTable {
9
10 struct Header {
11 uint32_t Magic;
12 uint16_t Version;
13 uint16_t HashFunction;
14 uint32_t NumBuckets;
15 uint32_t NumHashes;
16 uint32_t HeaderDataLength;
17 };
18
19 struct HeaderData {
20 typedef uint16_t AtomType;
21 uint32_t DIEOffsetBase;
22 SmallVector, 1> Atoms;
23 };
24
25 struct Header Hdr;
26 struct HeaderData HdrData;
27 DataExtractor AccelSection;
28 DataExtractor StringSection;
29 public:
30 DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection)
31 : AccelSection(AccelSection), StringSection(StringSection) {}
32
33 bool extract();
34 void dump(raw_ostream &OS);
35 };
36
37 }
88
99 #include "DWARFContext.h"
1010 #include "DWARFDebugArangeSet.h"
11 #include "DWARFAcceleratorTable.h"
1112
1213 #include "llvm/ADT/SmallString.h"
1314 #include "llvm/ADT/StringSwitch.h"
5657 OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
5758 }
5859 }
60 }
61
62 static void dumpAccelSection(raw_ostream &OS, StringRef Name, StringRef Data,
63 StringRef StringSection, bool LittleEndian) {
64 DataExtractor AccelSection(Data, LittleEndian, 0);
65 DataExtractor StrData(StringSection, LittleEndian, 0);
66 OS << "\n." << Name << " contents:\n";
67 DWARFAcceleratorTable Accel(AccelSection, StrData);
68 if (!Accel.extract())
69 return;
70 Accel.dump(OS);
5971 }
6072
6173 void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
217229 OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
218230 }
219231 }
232
233 if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
234 dumpAccelSection(OS, "apple_names", getAppleNamesSection(),
235 getStringSection(), isLittleEndian());
236
237 if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes)
238 dumpAccelSection(OS, "apple_types", getAppleTypesSection(),
239 getStringSection(), isLittleEndian());
240
241 if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces)
242 dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(),
243 getStringSection(), isLittleEndian());
244
245 if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC)
246 dumpAccelSection(OS, "apple_objc", getAppleObjCSection(),
247 getStringSection(), isLittleEndian());
220248 }
221249
222250 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
564592 .Case("debug_str.dwo", &StringDWOSection)
565593 .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
566594 .Case("debug_addr", &AddrSection)
595 .Case("apple_names", &AppleNamesSection)
596 .Case("apple_types", &AppleTypesSection)
597 .Case("apple_namespaces", &AppleNamespacesSection)
598 .Case("apple_namespac", &AppleNamespacesSection)
599 .Case("apple_objc", &AppleObjCSection)
567600 // Any more debug info sections go here.
568601 .Default(nullptr);
569602 if (SectionData) {
191191 virtual StringRef getStringOffsetDWOSection() = 0;
192192 virtual StringRef getRangeDWOSection() = 0;
193193 virtual StringRef getAddrSection() = 0;
194 virtual StringRef getAppleNamesSection() = 0;
195 virtual StringRef getAppleTypesSection() = 0;
196 virtual StringRef getAppleNamespacesSection() = 0;
197 virtual StringRef getAppleObjCSection() = 0;
194198
195199 static bool isSupportedVersion(unsigned version) {
196200 return version == 2 || version == 3 || version == 4;
235239 StringRef StringOffsetDWOSection;
236240 StringRef RangeDWOSection;
237241 StringRef AddrSection;
242 StringRef AppleNamesSection;
243 StringRef AppleTypesSection;
244 StringRef AppleNamespacesSection;
245 StringRef AppleObjCSection;
238246
239247 SmallVector, 4> UncompressedSections;
240248
255263 StringRef getPubTypesSection() override { return PubTypesSection; }
256264 StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; }
257265 StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; }
266 StringRef getAppleNamesSection() override { return AppleNamesSection; }
267 StringRef getAppleTypesSection() override { return AppleTypesSection; }
268 StringRef getAppleNamespacesSection() override { return AppleNamespacesSection; }
269 StringRef getAppleObjCSection() override { return AppleObjCSection; }
258270
259271 // Sections for DWARF5 split dwarf proposal.
260272 const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
9494 ; CHECK: .debug_pubtypes contents:
9595 ; CHECK-NOT: Offset
9696
97 ; CHECK: .apple{{.*}} contents:
98
9799 ; Function Attrs: nounwind uwtable
98100 define void @_Z2f1v() #0 {
99101 entry:
0 ; REQUIRES: object-emission
11
22 ; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck -implicit-check-not=DW_TAG %s
3 ; RUN: %llc_dwarf -dwarf-accel-tables=Enable -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --check-prefix=CHECK-ACCEL --check-prefix=CHECK %s
34
45 ; Build from source:
56 ; $ clang++ a.cpp b.cpp -g -c -emit-llvm
5051 ; CHECK: DW_TAG_formal_parameter
5152 ; CHECK: DW_AT_location
5253 ; CHECK: DW_AT_abstract_origin {{.*}} {0x[[ABS_VAR]]} "x"
54
55 ; Check that both the inline and the non out of line version of func are
56 ; correctly referenced in the accelerator table. Before r221837, the one
57 ; in the second compilation unit had a wrong offset
58 ; CHECK-ACCEL: .apple_names contents:
59 ; CHECK-ACCEL: Name{{.*}}"func"
60 ; CHECK-ACCEL-NOT: Name
61 ; CHECK-ACCEL: Atom[0]{{.*}}[[INLINED]]
62 ; CHECK-ACCEL-NOT: Name
63 ; CHECK-ACCEL: Atom[0]{{.*}}[[FUNC]]
5364
5465 @i = external global i32
5566
0 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-objc.x86_64.o | FileCheck %s
1
2 Gather some DIE indexes to verify the accelerator table contents.
3 CHECK: .debug_info contents
4 CHECK: [[TESTINTERFACE:0x[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
5 CHECK-NOT: DW_TAG
6 CHECK: DW_AT_name{{.*}}"TestInterface"
7 CHECK: [[READONLY:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
8 CHECK-NOT: DW_TAG
9 CHECK: DW_AT_name{{.*}}"-[TestInterface ReadOnly]"
10 CHECK: [[ASSIGN:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
11 CHECK-NOT: DW_TAG
12 CHECK: DW_AT_name{{.*}}"-[TestInterface Assign]"
13 CHECK: [[SETASSIGN:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
14 CHECK-NOT: DW_TAG
15 CHECK: DW_AT_name{{.*}}"-[TestInterface setAssign:]"
16
17
18 Check that the section header is printed correclty.
19 CHECK: .apple_names contents:
20 CHECK: Magic = 0x48415348
21 CHECK: Version = 0x0001
22 CHECK: Hash function = 0x00000000
23 CHECK: Bucket count = 11
24 CHECK: Hashes count = 22
25 CHECK: HeaderData length = 12
26 CHECK: DIE offset base = 0
27 CHECK: Number of atoms = 1
28 CHECK: Atom[0] Type: DW_ATOM_die_offset Form: DW_FORM_data4
29
30 Check that empty buckets are handled correctly.
31 CHECK: Bucket[2]
32 CHECK: EMPTY
33 CHECK: Bucket[3]
34
35 Check that the accelerators point to the right DIEs.
36 CHECK: Name:{{.*}}"-[TestInterface ReadOnly]"
37 CHECK-NOT: Name
38 CHECK: {Atom[0]: [[READONLY]]}
39 CHECK: Name:{{.*}}"-[TestInterface setAssign:]"
40 CHECK-NOT: Name
41 CHECK: {Atom[0]: [[SETASSIGN]]}
42 CHECK: Name:{{.*}}"-[TestInterface Assign]"
43 CHECK-NOT: Name
44 CHECK: {Atom[0]: [[ASSIGN]]}
45
46 Check that types are referenced correctly.
47 CHECK: .apple_types contents:
48 CHECK: Name{{.*}}"TestInterface"
49 CHECK-NOT: Name
50 CHECK: {Atom[0]: [[TESTINTERFACE]]}
51
52 Check that an empty ecceleratorsection is handled correctly.
53 CHECK: .apple_namespaces contents:
54 CHECK-NOT: Magic
55
56 Check ObjC specific accelerators.
57 CHECK: .apple_objc contents:
58 CHECK: Name{{.*}}"TestInterface"
59 CHECK-NOT Name
60 CHECK: {Atom[0]: [[READONLY]]}
61 CHECK: {Atom[0]: [[ASSIGN]]}
62 CHECK: {Atom[0]: [[SETASSIGN]]}
4444 clEnumValN(DIDT_All, "all", "Dump all debug sections"),
4545 clEnumValN(DIDT_Abbrev, "abbrev", ".debug_abbrev"),
4646 clEnumValN(DIDT_AbbrevDwo, "abbrev.dwo", ".debug_abbrev.dwo"),
47 clEnumValN(DIDT_AppleNames, "apple_names", ".apple_names"),
48 clEnumValN(DIDT_AppleTypes, "apple_types", ".apple_types"),
49 clEnumValN(DIDT_AppleNamespaces, "apple_namespaces", ".apple_namespaces"),
50 clEnumValN(DIDT_AppleObjC, "apple_objc", ".apple_objc"),
4751 clEnumValN(DIDT_Aranges, "aranges", ".debug_aranges"),
4852 clEnumValN(DIDT_Info, "info", ".debug_info"),
4953 clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),