Skip to content

Commit 380ac53

Browse files
[DebugNames] Implement Entry::GetParentEntry query (#78760)
This commit introduces a helper function to DWARFAcceleratorTable::Entry which follows DW_IDX_Parent attributes to returns the corresponding parent Entry in the table. It is tested by enhancing dwarfdump so that it now prints: 1. When data is corrupt. 2. When parent information is present, but the parent is not indexed. 3. The parent entry offset, when the parent is present and indexed. This is printed in terms a real entry offset (the same that gets printed at the start of each entry: "Entry @ 0x..."), instead of the encoded number in the table (which is an offset from the start off the Entry list). This makes it easy to visually inspect the dwarfdump and check what the parent is.
1 parent 5db2e58 commit 380ac53

File tree

8 files changed

+97
-26
lines changed

8 files changed

+97
-26
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,16 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
460460
/// Returns the Offset of the DIE within the containing CU or TU.
461461
std::optional<uint64_t> getDIEUnitOffset() const;
462462

463+
/// Returns true if this Entry has information about its parent DIE (i.e. if
464+
/// it has an IDX_parent attribute)
465+
bool hasParentInformation() const;
466+
467+
/// Returns the Entry corresponding to the parent of the DIE represented by
468+
/// `this` Entry. If the parent is not in the table, nullopt is returned.
469+
/// Precondition: hasParentInformation() == true.
470+
/// An error is returned for ill-formed tables.
471+
Expected<std::optional<DWARFDebugNames::Entry>> getParentDIEEntry() const;
472+
463473
/// Return the Abbreviation that can be used to interpret the raw values of
464474
/// this Accelerator Entry.
465475
const Abbrev &getAbbrev() const { return *Abbr; }
@@ -469,6 +479,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
469479
std::optional<DWARFFormValue> lookup(dwarf::Index Index) const;
470480

471481
void dump(ScopedPrinter &W) const;
482+
void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const;
472483

473484
friend class NameIndex;
474485
friend class ValueIterator;
@@ -609,6 +620,13 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
609620

610621
Expected<Entry> getEntry(uint64_t *Offset) const;
611622

623+
/// Returns the Entry at the relative `Offset` from the start of the Entry
624+
/// pool.
625+
Expected<Entry> getEntryAtRelativeOffset(uint64_t Offset) const {
626+
auto OffsetFromSection = Offset + this->EntriesBase;
627+
return getEntry(&OffsetFromSection);
628+
}
629+
612630
/// Look up all entries in this Name Index matching \c Key.
613631
iterator_range<ValueIterator> equal_range(StringRef Key) const;
614632

llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,10 @@ DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
611611
return std::nullopt;
612612
}
613613

614+
bool DWARFDebugNames::Entry::hasParentInformation() const {
615+
return lookup(dwarf::DW_IDX_parent).has_value();
616+
}
617+
614618
std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
615619
if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
616620
return Off->getAsReferenceUVal();
@@ -650,13 +654,48 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
650654
return std::nullopt;
651655
}
652656

657+
Expected<std::optional<DWARFDebugNames::Entry>>
658+
DWARFDebugNames::Entry::getParentDIEEntry() const {
659+
// The offset of the accelerator table entry for the parent.
660+
std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
661+
assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
662+
663+
if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
664+
return std::nullopt;
665+
return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
666+
}
667+
668+
void DWARFDebugNames::Entry::dumpParentIdx(
669+
ScopedPrinter &W, const DWARFFormValue &FormValue) const {
670+
Expected<std::optional<Entry>> ParentEntry = getParentDIEEntry();
671+
if (!ParentEntry) {
672+
W.getOStream() << "<invalid offset data>";
673+
consumeError(ParentEntry.takeError());
674+
return;
675+
}
676+
677+
if (!ParentEntry->has_value()) {
678+
W.getOStream() << "<parent not indexed>";
679+
return;
680+
}
681+
682+
auto AbsoluteOffset = NameIdx->EntriesBase + FormValue.getRawUValue();
683+
W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
684+
}
685+
653686
void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
654687
W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
655688
W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
656689
assert(Abbr->Attributes.size() == Values.size());
657690
for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
658-
W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
659-
std::get<1>(Tuple).dump(W.getOStream());
691+
auto Index = std::get<0>(Tuple).Index;
692+
W.startLine() << formatv("{0}: ", Index);
693+
694+
auto FormValue = std::get<1>(Tuple);
695+
if (Index == dwarf::Index::DW_IDX_parent)
696+
dumpParentIdx(W, FormValue);
697+
else
698+
FormValue.dump(W.getOStream());
660699
W.getOStream() << '\n';
661700
}
662701
}

llvm/test/CodeGen/X86/dwarf-headers.o

Whitespace-only changes.

llvm/test/DebugInfo/Generic/debug-names-one-cu.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@
3535
; CHECK-NEXT: Abbrev: [[ABBREV]]
3636
; CHECK-NEXT: Tag: DW_TAG_variable
3737
; CHECK-NEXT: DW_IDX_die_offset: 0x{{[0-9a-f]*}}
38-
; CHECK-NEXT: DW_IDX_parent: true
38+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
3939
; CHECK-NEXT: }
4040

4141
; CHECK: String: 0x{{[0-9a-f]*}} "foobar"
4242
; CHECK-NEXT: Entry
4343
; CHECK-NEXT: Abbrev: [[ABBREV]]
4444
; CHECK-NEXT: Tag: DW_TAG_variable
4545
; CHECK-NEXT: DW_IDX_die_offset: 0x{{[0-9a-f]*}}
46-
; CHECK-NEXT: DW_IDX_parent: true
46+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
4747
; CHECK-NEXT: }
4848

4949
; VERIFY: No errors.

llvm/test/DebugInfo/X86/debug-names-dwarf64.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
; CHECK-NEXT: Abbrev: [[ABBREV]]
6060
; CHECK-NEXT: Tag: DW_TAG_base_type
6161
; CHECK-NEXT: DW_IDX_die_offset: [[TYPEDIE]]
62-
; CHECK-NEXT: DW_IDX_parent: true
62+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
6363
; CHECK-NEXT: }
6464
; CHECK-NEXT: }
6565
; CHECK-NEXT: ]
@@ -71,17 +71,17 @@
7171
; CHECK-NEXT: Abbrev: [[ABBREV1]]
7272
; CHECK-NEXT: Tag: DW_TAG_variable
7373
; CHECK-NEXT: DW_IDX_die_offset: [[VARDIE]]
74-
; CHECK-NEXT: DW_IDX_parent: true
74+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
7575
; CHECK-NEXT: }
7676
; CHECK-NEXT: }
7777
; CHECK-NEXT: Name 3 {
7878
; CHECK-NEXT: Hash: 0x7C96FE71
7979
; CHECK-NEXT: String: {{.+}} "func"
80-
; CHECK-NEXT: Entry @ {{.+}} {
80+
; CHECK-NEXT: Entry @ [[FUNC_ENTRY:0x.+]] {
8181
; CHECK-NEXT: Abbrev: [[ABBREV_SP]]
8282
; CHECK-NEXT: Tag: DW_TAG_subprogram
8383
; CHECK-NEXT: DW_IDX_die_offset: [[SPDIE]]
84-
; CHECK-NEXT: DW_IDX_parent: true
84+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
8585
; CHECK-NEXT: }
8686
; CHECK-NEXT: }
8787
; CHECK-NEXT: ]
@@ -96,7 +96,7 @@
9696
; CHECK-NEXT: Abbrev: [[ABBREV_LABEL]]
9797
; CHECK-NEXT: Tag: DW_TAG_label
9898
; CHECK-NEXT: DW_IDX_die_offset: [[LABELDIE]]
99-
; CHECK-NEXT: DW_IDX_parent: 0x{{.*}}
99+
; CHECK-NEXT: DW_IDX_parent: Entry @ [[FUNC_ENTRY]]
100100
; CHECK-NEXT: }
101101
; CHECK-NEXT: }
102102
; CHECK-NEXT: ]

llvm/test/DebugInfo/X86/debug-names-parents-same-offset.ll

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,30 @@
2121
; CHECK-NEXT: Abbrev: [[ABBREV:0x.*]]
2222
; CHECK-NEXT: Tag: DW_TAG_structure_type
2323
; CHECK-NEXT: DW_IDX_type_unit: 0x01
24-
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffset:0x.*]]
25-
; CHECK-NEXT: DW_IDX_parent: [[Parent1:0x.*]]
24+
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffsetStruct:0x.*]]
25+
; CHECK-NEXT: DW_IDX_parent: Entry @ [[Parent2:0x.*]]
26+
; CHECK: String: {{.*}} "MyNamespace"
27+
; CHECK-NEXT: Entry @ [[Parent1:0x.*]] {
28+
; CHECK-NEXT: Abbrev: {{.*}}
29+
; CHECK-NEXT: Tag: DW_TAG_namespace
30+
; CHECK-NEXT: DW_IDX_type_unit: 0x00
31+
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffsetNamespace:0x.*]]
32+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
33+
; CHECK-NEXT: }
34+
; CHECK-NEXT: Entry @ [[Parent2]] {
35+
; CHECK-NEXT: Abbrev: {{.*}}
36+
; CHECK-NEXT: Tag: DW_TAG_namespace
37+
; CHECK-NEXT: DW_IDX_type_unit: 0x01
38+
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffsetNamespace:0x.*]]
39+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
40+
; CHECK-NEXT: }
2641
; CHECK: String: {{.*}} "MyStruct1"
2742
; CHECK-NEXT: Entry @ {{.*}} {
2843
; CHECK-NEXT: Abbrev: [[ABBREV]]
2944
; CHECK-NEXT: Tag: DW_TAG_structure_type
3045
; CHECK-NEXT: DW_IDX_type_unit: 0x00
31-
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffset:0x.*]]
32-
; CHECK-NOT: DW_IDX_parent: [[Parent1]]
33-
; CHECK-NEXT: DW_IDX_parent: 0x{{.*}}
46+
; CHECK-NEXT: DW_IDX_die_offset: [[DieOffsetStruct:0x.*]]
47+
; CHECK-NEXT: DW_IDX_parent: Entry @ [[Parent1]]
3448

3549

3650
%"struct.MyNamespace::MyStruct1" = type { i8 }

llvm/test/DebugInfo/X86/debug-names-types.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
; CHECK-NEXT: Abbrev: [[ABBREV]]
7474
; CHECK-NEXT: Tag: DW_TAG_base_type
7575
; CHECK-NEXT: DW_IDX_die_offset: 0x0000003e
76-
; CHECK-NEXT: DW_IDX_parent: true
76+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
7777
; CHECK-NEXT: }
7878
; CHECK-NEXT: }
7979
; CHECK-NEXT: ]
@@ -86,13 +86,13 @@
8686
; CHECK-NEXT: Tag: DW_TAG_structure_type
8787
; CHECK-NEXT: DW_IDX_type_unit: 0x00
8888
; CHECK-NEXT: DW_IDX_die_offset: 0x00000023
89-
; CHECK-NEXT: DW_IDX_parent: true
89+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
9090
; CHECK-NEXT: }
9191
; CHECK-NEXT: Entry @ {{.+}} {
9292
; CHECK-NEXT: Abbrev: [[ABBREV1]]
9393
; CHECK-NEXT: Tag: DW_TAG_structure_type
9494
; CHECK-NEXT: DW_IDX_die_offset: 0x00000042
95-
; CHECK-NEXT: DW_IDX_parent: true
95+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
9696
; CHECK-NEXT: }
9797
; CHECK-NEXT: }
9898
; CHECK-NEXT: ]
@@ -104,7 +104,7 @@
104104
; CHECK-NEXT: Abbrev: [[ABBREV2]]
105105
; CHECK-NEXT: Tag: DW_TAG_subprogram
106106
; CHECK-NEXT: DW_IDX_die_offset: 0x00000023
107-
; CHECK-NEXT: DW_IDX_parent: true
107+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
108108
; CHECK-NEXT: }
109109
; CHECK-NEXT: }
110110
; CHECK-NEXT: ]
@@ -117,7 +117,7 @@
117117
; CHECK-NEXT: Tag: DW_TAG_base_type
118118
; CHECK-NEXT: DW_IDX_type_unit: 0x00
119119
; CHECK-NEXT: DW_IDX_die_offset: 0x00000038
120-
; CHECK-NEXT: DW_IDX_parent: true
120+
; CHECK-NEXT: DW_IDX_parent: <parent not indexed>
121121
; CHECK-NEXT: }
122122
; CHECK-NEXT: }
123123
; CHECK-NEXT: ]
@@ -176,7 +176,7 @@
176176
; CHECK-SPLIT-NEXT: Abbrev: [[ABBREV2]]
177177
; CHECK-SPLIT-NEXT: Tag: DW_TAG_base_type
178178
; CHECK-SPLIT-NEXT: DW_IDX_die_offset: 0x00000035
179-
; CHECK-SPLIT-NEXT: DW_IDX_parent: true
179+
; CHECK-SPLIT-NEXT: DW_IDX_parent: <parent not indexed>
180180
; CHECK-SPLIT-NEXT: }
181181
; CHECK-SPLIT-NEXT: }
182182
; CHECK-SPLIT-NEXT: ]
@@ -189,13 +189,13 @@
189189
; CHECK-SPLIT-NEXT: Tag: DW_TAG_structure_type
190190
; CHECK-SPLIT-NEXT: DW_IDX_type_unit: 0x00
191191
; CHECK-SPLIT-NEXT: DW_IDX_die_offset: 0x00000021
192-
; CHECK-SPLIT-NEXT: DW_IDX_parent: true
192+
; CHECK-SPLIT-NEXT: DW_IDX_parent: <parent not indexed>
193193
; CHECK-SPLIT-NEXT: }
194194
; CHECK-SPLIT-NEXT: Entry @ {{.*}} {
195195
; CHECK-SPLIT-NEXT: Abbrev: [[ABBREV]]
196196
; CHECK-SPLIT-NEXT: Tag: DW_TAG_structure_type
197197
; CHECK-SPLIT-NEXT: DW_IDX_die_offset: 0x00000039
198-
; CHECK-SPLIT-NEXT: DW_IDX_parent: true
198+
; CHECK-SPLIT-NEXT: DW_IDX_parent: <parent not indexed>
199199
; CHECK-SPLIT-NEXT: }
200200
; CHECK-SPLIT-NEXT: }
201201
; CHECK-SPLIT-NEXT: ]
@@ -207,7 +207,7 @@
207207
; CHECK-SPLIT-NEXT: Abbrev: [[ABBREV3]]
208208
; CHECK-SPLIT-NEXT: Tag: DW_TAG_subprogram
209209
; CHECK-SPLIT-NEXT: DW_IDX_die_offset: 0x0000001a
210-
; CHECK-SPLIT-NEXT: DW_IDX_parent: true
210+
; CHECK-SPLIT-NEXT: DW_IDX_parent: <parent not indexed>
211211
; CHECK-SPLIT-NEXT: }
212212
; CHECK-SPLIT-NEXT: }
213213
; CHECK-SPLIT-NEXT: ]
@@ -220,7 +220,7 @@
220220
; CHECK-SPLIT-NEXT: Tag: DW_TAG_base_type
221221
; CHECK-SPLIT-NEXT: DW_IDX_type_unit: 0x00
222222
; CHECK-SPLIT-NEXT: DW_IDX_die_offset: 0x00000036
223-
; CHECK-SPLIT-NEXT: DW_IDX_parent: true
223+
; CHECK-SPLIT-NEXT: DW_IDX_parent: <parent not indexed>
224224
; CHECK-SPLIT-NEXT: }
225225
; CHECK-SPLIT-NEXT: }
226226
; CHECK-SPLIT-NEXT: ]

llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ DWARF-NEXT: Entry {{.*}} {
2323
DWARF-NEXT: Abbrev: {{.*}}
2424
DWARF-NEXT: Tag: DW_TAG_namespace
2525
DWARF: DW_IDX_die_offset: [[NAMESPACE]]
26-
DWARF-NEXT: DW_IDX_parent: 0x{{.*}}
26+
DWARF-NEXT: DW_IDX_parent: Entry @ 0x{{.*}}
2727
DWARF-NEXT: }
2828
DWARF-NEXT: Entry {{.*}} {
2929
DWARF-NEXT: Abbrev: {{.*}}
3030
DWARF: Tag: DW_TAG_imported_declaration
3131
DWARF: DW_IDX_die_offset: 0x0000005c
32-
DWARF-NEXT: DW_IDX_parent: 0x{{.*}}
32+
DWARF-NEXT: DW_IDX_parent: Entry @ 0x{{.*}}
3333
DWARF-NEXT: }
3434
DWARF-NEXT: }
3535

0 commit comments

Comments
 (0)