Skip to content

Commit 47c3472

Browse files
committedMar 9, 2018
[DebugInfo/AccelTable] Fix inconsistency in getDIEOffset implementations
Summary: Even though the getDIEOffset offset function was common for the two accelerator table implementations, it was doing two different things: for the Apple tables, it was returning the die offset relative to the start of the section, whereas for DWARF v5 tables, it was relative to the start of the CU. I resolve this by renaming the function to getDIESectionOffset to make it obvious what the function returns, and change the DWARF implementation to return the section offset. I also keep the CU-relative accessor, but only in the DWARF implementation (there is no way to get this information for the Apple tables). This was not caught by existing tests because the hand-written inputs also erroneously used section offsets instead of CU-relative ones. While looking at this, I noticed that the Apple implementation was not fully correct either -- the header contains a DIEOffsetBase field, which should be added to offsets encoded with the DW_FORM_ref*** family, but this was not being used. This went unnoticed because all current writers set this field to zero anyway. I fix this as well and add a hand-written test which demonstrates the issue. Reviewers: JDevlieghere, dblaikie Subscribers: aprantl, llvm-commits Differential Revision: https://reviews.llvm.org/D44202 llvm-svn: 327116
1 parent 893cbc2 commit 47c3472

File tree

6 files changed

+204
-20
lines changed

6 files changed

+204
-20
lines changed
 

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

+15-6
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ class DWARFAcceleratorTable {
5656
/// in this Accelerator Entry.
5757
virtual Optional<uint64_t> getCUOffset() const = 0;
5858

59-
/// Returns the Offset of the Debug Info Entry associated with this
59+
/// Returns the Section Offset of the Debug Info Entry associated with this
6060
/// Accelerator Entry or None if the DIE offset is not recorded in this
61-
/// Accelerator Entry.
62-
virtual Optional<uint64_t> getDIEOffset() const = 0;
61+
/// Accelerator Entry. The returned offset is relative to the start of the
62+
/// Section containing the DIE.
63+
virtual Optional<uint64_t> getDIESectionOffset() const = 0;
6364

6465
/// Returns the Tag of the Debug Info Entry associated with this
6566
/// Accelerator Entry or None if the Tag is not recorded in this
@@ -104,6 +105,8 @@ class AppleAcceleratorTable : public DWARFAcceleratorTable {
104105

105106
uint32_t DIEOffsetBase;
106107
SmallVector<std::pair<AtomType, Form>, 3> Atoms;
108+
109+
Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
107110
};
108111

109112
struct Header Hdr;
@@ -127,7 +130,7 @@ class AppleAcceleratorTable : public DWARFAcceleratorTable {
127130

128131
public:
129132
Optional<uint64_t> getCUOffset() const override;
130-
Optional<uint64_t> getDIEOffset() const override;
133+
Optional<uint64_t> getDIESectionOffset() const override;
131134
Optional<dwarf::Tag> getTag() const override;
132135

133136
/// Returns the value of the Atom in this Accelerator Entry, if the Entry
@@ -284,18 +287,24 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
284287
/// Index or None if this Accelerator Entry does not have an associated
285288
/// Compilation Unit. It is up to the user to verify that the returned Index
286289
/// is valid in the owning NameIndex (or use getCUOffset(), which will
287-
/// handle that check itself).
290+
/// handle that check itself). Note that entries in NameIndexes which index
291+
/// just a single Compilation Unit are implicitly associated with that unit,
292+
/// so this function will return 0 even without an explicit
293+
/// DW_IDX_compile_unit attribute.
288294
Optional<uint64_t> getCUIndex() const;
289295

290296
public:
291297
Optional<uint64_t> getCUOffset() const override;
292-
Optional<uint64_t> getDIEOffset() const override;
298+
Optional<uint64_t> getDIESectionOffset() const override;
293299
Optional<dwarf::Tag> getTag() const override { return tag(); }
294300

295301
/// .debug_names-specific getter, which always succeeds (DWARF v5 index
296302
/// entries always have a tag).
297303
dwarf::Tag tag() const { return Abbr->Tag; }
298304

305+
/// Returns the Offset of the DIE within the containing CU or TU.
306+
Optional<uint64_t> getDIEUnitOffset() const;
307+
299308
/// Return the Abbreviation that can be used to interpret the raw values of
300309
/// this Accelerator Entry.
301310
const Abbrev &getAbbrev() const { return *Abbr; }

‎llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp

+33-8
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,23 @@ void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
159159
W.printNumber("HeaderData length", HeaderDataLength);
160160
}
161161

162+
Optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
163+
Optional<DWARFFormValue> Value) const {
164+
if (!Value)
165+
return None;
166+
167+
switch (Value->getForm()) {
168+
case dwarf::DW_FORM_ref1:
169+
case dwarf::DW_FORM_ref2:
170+
case dwarf::DW_FORM_ref4:
171+
case dwarf::DW_FORM_ref8:
172+
case dwarf::DW_FORM_ref_udata:
173+
return Value->getRawUValue() + DIEOffsetBase;
174+
default:
175+
return Value->getAsSectionOffset();
176+
}
177+
}
178+
162179
bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
163180
SmallVectorImpl<DWARFFormValue> &AtomForms,
164181
uint32_t *DataOffset) const {
@@ -276,16 +293,12 @@ AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType Atom) const {
276293
return None;
277294
}
278295

279-
Optional<uint64_t> AppleAcceleratorTable::Entry::getDIEOffset() const {
280-
if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_ATOM_die_offset))
281-
return Off->getAsSectionOffset();
282-
return None;
296+
Optional<uint64_t> AppleAcceleratorTable::Entry::getDIESectionOffset() const {
297+
return HdrData->extractOffset(lookup(dwarf::DW_ATOM_die_offset));
283298
}
284299

285300
Optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
286-
if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_ATOM_cu_offset))
287-
return Off->getAsSectionOffset();
288-
return None;
301+
return HdrData->extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
289302
}
290303

291304
Optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
@@ -537,7 +550,7 @@ DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
537550
return None;
538551
}
539552

540-
Optional<uint64_t> DWARFDebugNames::Entry::getDIEOffset() const {
553+
Optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
541554
if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
542555
return Off->getAsSectionOffset();
543556
return None;
@@ -546,6 +559,10 @@ Optional<uint64_t> DWARFDebugNames::Entry::getDIEOffset() const {
546559
Optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
547560
if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
548561
return Off->getAsUnsignedConstant();
562+
// In a per-CU index, the entries without a DW_IDX_compile_unit attribute
563+
// implicitly refer to the single CU.
564+
if (NameIdx->getCUCount() == 1)
565+
return 0;
549566
return None;
550567
}
551568

@@ -556,6 +573,14 @@ Optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
556573
return NameIdx->getCUOffset(*Index);
557574
}
558575

576+
Optional<uint64_t> DWARFDebugNames::Entry::getDIESectionOffset() const {
577+
Optional<uint64_t> CUOff = getCUOffset();
578+
Optional<uint64_t> DIEOff = getDIEUnitOffset();
579+
if (CUOff && DIEOff)
580+
return *CUOff + *DIEOff;
581+
return None;
582+
}
583+
559584
void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
560585
W.printHex("Abbrev", Abbr->Code);
561586
W.startLine() << "Tag: " << formatTag(Abbr->Tag) << "\n";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# This test sets non-zero Die Offset Base field in the accelerator table header,
2+
# and makes sure it is *not* added to the DW_FORM_data*** forms.
3+
4+
# RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t
5+
# RUN: llvm-dwarfdump -find=main %t | FileCheck %s
6+
7+
# CHECK: DW_TAG_subprogram
8+
# CHECK-NEXT: DW_AT_name ("main")
9+
# CHECK-NEXT: DW_AT_external
10+
11+
.section __DWARF,__debug_str,regular,debug
12+
Ldebug_str:
13+
Lstring_producer:
14+
.asciz "Hand-written dwarf"
15+
Lstring_main:
16+
.asciz "main"
17+
18+
.section __DWARF,__debug_abbrev,regular,debug
19+
.byte 1 # Abbreviation Code
20+
.byte 17 # DW_TAG_compile_unit
21+
.byte 1 # DW_CHILDREN_yes
22+
.byte 37 # DW_AT_producer
23+
.byte 14 # DW_FORM_strp
24+
.byte 19 # DW_AT_language
25+
.byte 5 # DW_FORM_data2
26+
.byte 0 # EOM(1)
27+
.byte 0 # EOM(2)
28+
.byte 2 # Abbreviation Code
29+
.byte 46 # DW_TAG_subprogram
30+
.byte 0 # DW_CHILDREN_no
31+
.byte 3 # DW_AT_name
32+
.byte 14 # DW_FORM_strp
33+
.byte 63 # DW_AT_external
34+
.byte 25 # DW_FORM_flag_present
35+
.byte 0 # EOM(1)
36+
.byte 0 # EOM(2)
37+
.byte 0 # EOM(3)
38+
39+
.section __DWARF,__debug_info,regular,debug
40+
Ldebug_info:
41+
.long Lcu_end0-Lcu_start0 # Length of Unit
42+
Lcu_start0:
43+
.short 4 # DWARF version number
44+
.long 0 # Offset Into Abbrev. Section
45+
.byte 8 # Address Size (in bytes)
46+
.byte 1 # Abbrev [1] DW_TAG_compile_unit
47+
.long Lstring_producer-Ldebug_str # DW_AT_producer
48+
.short 12 # DW_AT_language
49+
Ldie_main:
50+
.byte 2 # Abbrev [2] DW_TAG_subprogram
51+
.long Lstring_main-Ldebug_str # DW_AT_name
52+
# DW_AT_external
53+
.byte 0 # End Of Children Mark
54+
Lcu_end0:
55+
56+
.section __DWARF,__apple_names,regular,debug
57+
Lnames_begin:
58+
.long 1212240712 ## Header Magic
59+
.short 1 ## Header Version
60+
.short 0 ## Header Hash Function
61+
.long 1 ## Header Bucket Count
62+
.long 1 ## Header Hash Count
63+
.long 12 ## Header Data Length
64+
.long 1 ## HeaderData Die Offset Base
65+
.long 1 ## HeaderData Atom Count
66+
.short 1 ## DW_ATOM_die_offset
67+
.short 6 ## DW_FORM_data4
68+
.long 0 ## Bucket 0
69+
.long 2090499946 ## Hash in Bucket 0
70+
.long LNames0-Lnames_begin ## Offset in Bucket 0
71+
LNames0:
72+
.long Lstring_main-Ldebug_str ## main
73+
.long 1 ## Num DIEs
74+
.long Ldie_main-Ldebug_info
75+
.long 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# This test sets non-zero Die Offset Base field in the accelerator table header,
2+
# and makes sure it is added to the DW_FORM_ref*** forms.
3+
4+
# RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t
5+
# RUN: llvm-dwarfdump -find=main %t | FileCheck %s
6+
7+
# CHECK: DW_TAG_subprogram
8+
# CHECK-NEXT: DW_AT_name ("main")
9+
# CHECK-NEXT: DW_AT_external
10+
11+
.section __DWARF,__debug_str,regular,debug
12+
Ldebug_str:
13+
Lstring_producer:
14+
.asciz "Hand-written dwarf"
15+
Lstring_main:
16+
.asciz "main"
17+
18+
.section __DWARF,__debug_abbrev,regular,debug
19+
.byte 1 # Abbreviation Code
20+
.byte 17 # DW_TAG_compile_unit
21+
.byte 1 # DW_CHILDREN_yes
22+
.byte 37 # DW_AT_producer
23+
.byte 14 # DW_FORM_strp
24+
.byte 19 # DW_AT_language
25+
.byte 5 # DW_FORM_data2
26+
.byte 0 # EOM(1)
27+
.byte 0 # EOM(2)
28+
.byte 2 # Abbreviation Code
29+
.byte 46 # DW_TAG_subprogram
30+
.byte 0 # DW_CHILDREN_no
31+
.byte 3 # DW_AT_name
32+
.byte 14 # DW_FORM_strp
33+
.byte 63 # DW_AT_external
34+
.byte 25 # DW_FORM_flag_present
35+
.byte 0 # EOM(1)
36+
.byte 0 # EOM(2)
37+
.byte 0 # EOM(3)
38+
39+
.section __DWARF,__debug_info,regular,debug
40+
Ldebug_info:
41+
.long Lcu_end0-Lcu_start0 # Length of Unit
42+
Lcu_start0:
43+
.short 4 # DWARF version number
44+
.long 0 # Offset Into Abbrev. Section
45+
.byte 8 # Address Size (in bytes)
46+
.byte 1 # Abbrev [1] DW_TAG_compile_unit
47+
.long Lstring_producer-Ldebug_str # DW_AT_producer
48+
.short 12 # DW_AT_language
49+
Ldie_main:
50+
.byte 2 # Abbrev [2] DW_TAG_subprogram
51+
.long Lstring_main-Ldebug_str # DW_AT_name
52+
# DW_AT_external
53+
.byte 0 # End Of Children Mark
54+
Lcu_end0:
55+
56+
.section __DWARF,__apple_names,regular,debug
57+
Lnames_begin:
58+
.long 1212240712 ## Header Magic
59+
.short 1 ## Header Version
60+
.short 0 ## Header Hash Function
61+
.long 1 ## Header Bucket Count
62+
.long 1 ## Header Hash Count
63+
.long 12 ## Header Data Length
64+
.long 1 ## HeaderData Die Offset Base
65+
.long 1 ## HeaderData Atom Count
66+
.short 1 ## DW_ATOM_die_offset
67+
.short 0x13 ## DW_FORM_ref4
68+
.long 0 ## Bucket 0
69+
.long 2090499946 ## Hash in Bucket 0
70+
.long LNames0-Lnames_begin ## Offset in Bucket 0
71+
LNames0:
72+
.long Lstring_main-Ldebug_str ## main
73+
.long 1 ## Num DIEs
74+
.long Ldie_main-Ldebug_info-1
75+
.long 0

‎llvm/test/tools/llvm-dwarfdump/X86/debug-names-find.s

+5-5
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@
129129
.Lnames_entries0:
130130
.Lnames0:
131131
.byte 46 # Abbrev code
132-
.long .Ldie_bar # DW_IDX_die_offset
132+
.long .Ldie_bar-.Lcu_begin0 # DW_IDX_die_offset
133133
.long 0 # End of list: bar
134134
.Lnames1:
135135
.byte 46 # Abbrev code
136-
.long .Ldie_foo # DW_IDX_die_offset
136+
.long .Ldie_foo-.Lcu_begin0 # DW_IDX_die_offset
137137
.long 0 # End of list: foo
138138
.Lnames2:
139139
.byte 46 # Abbrev code
140-
.long .Ldie_foo # DW_IDX_die_offset
140+
.long .Ldie_foo-.Lcu_begin0 # DW_IDX_die_offset
141141
.long 0 # End of list: _Z3foov
142142
.p2align 2
143143
.Lnames_end0:
@@ -171,12 +171,12 @@
171171
.Lnames_entries1:
172172
.Lnames3:
173173
.byte 46 # Abbrev code
174-
.long .Ldie_baz # DW_IDX_die_offset
174+
.long .Ldie_baz-.Lcu_begin1 # DW_IDX_die_offset
175175
.long 0 # End of list: baz
176176
.p2align 2
177177
.Lnames4:
178178
.byte 46 # Abbrev code
179-
.long .Ldie_bazz # DW_IDX_die_offset
179+
.long .Ldie_bazz-.Lcu_begin1 # DW_IDX_die_offset
180180
.long 0 # End of list: baz
181181
.p2align 2
182182
.Lnames_end1:

‎llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ template <typename AccelTable>
340340
static llvm::Optional<uint64_t> getDIEOffset(const AccelTable &Accel,
341341
StringRef Name) {
342342
for (const auto &Entry : Accel.equal_range(Name))
343-
if (llvm::Optional<uint64_t> Off = Entry.getDIEOffset())
343+
if (llvm::Optional<uint64_t> Off = Entry.getDIESectionOffset())
344344
return *Off;
345345
return None;
346346
}

0 commit comments

Comments
 (0)
Please sign in to comment.