Skip to content

Commit af11c55

Browse files
committed
[DebugInfo] Fix reading DWARFv5 type units in DWP.
In DWARFv5, type units are stored in .debug_info sections, along with compilation units, and they are distinguished by the unit_type field in the header, not by the name of the section. It is impossible to associate the correct index section of a DWP file with the unit before the unit's header is read. This patch fixes reading DWARFv5 type units by parsing the header first and then applying the index entry according to the actual unit type. Differential Revision: https://reviews.llvm.org/D77552
1 parent 0bc2eab commit af11c55

File tree

4 files changed

+111
-28
lines changed

4 files changed

+111
-28
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,14 @@ class DWARFUnitHeader {
7070

7171
public:
7272
/// Parse a unit header from \p debug_info starting at \p offset_ptr.
73+
/// Note that \p SectionKind is used as a hint to guess the unit type
74+
/// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
75+
/// explicitly defined in the header and the hint is ignored.
7376
bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
74-
uint64_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
75-
const DWARFUnitIndex *Index = nullptr,
76-
const DWARFUnitIndex::Entry *Entry = nullptr);
77+
uint64_t *offset_ptr, DWARFSectionKind SectionKind);
78+
// For units in DWARF Package File, remember the index entry and update
79+
// the abbreviation offset read by extract().
80+
bool applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
7781
uint64_t getOffset() const { return Offset; }
7882
const dwarf::FormParams &getFormParams() const { return FormParams; }
7983
uint16_t getVersion() const { return FormParams.Version; }

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ void DWARFUnitVector::addUnitsImpl(
7373
DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
7474
if (!Data.isValidOffset(Offset))
7575
return nullptr;
76-
const DWARFUnitIndex *Index = nullptr;
77-
if (IsDWO)
78-
Index = &getDWARFUnitIndex(Context, SectionKind);
7976
DWARFUnitHeader Header;
80-
if (!Header.extract(Context, Data, &Offset, SectionKind, Index,
81-
IndexEntry))
77+
if (!Header.extract(Context, Data, &Offset, SectionKind))
78+
return nullptr;
79+
if (!IndexEntry && IsDWO) {
80+
const DWARFUnitIndex &Index = getDWARFUnitIndex(
81+
Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO);
82+
IndexEntry = Index.getFromOffset(Header.getOffset());
83+
}
84+
if (IndexEntry && !Header.applyIndexEntry(IndexEntry))
8285
return nullptr;
8386
std::unique_ptr<DWARFUnit> U;
8487
if (Header.isTypeUnit())
@@ -251,14 +254,10 @@ Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
251254
bool DWARFUnitHeader::extract(DWARFContext &Context,
252255
const DWARFDataExtractor &debug_info,
253256
uint64_t *offset_ptr,
254-
DWARFSectionKind SectionKind,
255-
const DWARFUnitIndex *Index,
256-
const DWARFUnitIndex::Entry *Entry) {
257+
DWARFSectionKind SectionKind) {
257258
Offset = *offset_ptr;
258259
Error Err = Error::success();
259-
IndexEntry = Entry;
260-
if (!IndexEntry && Index)
261-
IndexEntry = Index->getFromOffset(*offset_ptr);
260+
IndexEntry = nullptr;
262261
std::tie(Length, FormParams.Format) =
263262
debug_info.getInitialLength(offset_ptr, &Err);
264263
FormParams.Version = debug_info.getU16(offset_ptr, &Err);
@@ -288,19 +287,6 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
288287
if (errorToBool(std::move(Err)))
289288
return false;
290289

291-
if (IndexEntry) {
292-
if (AbbrOffset)
293-
return false;
294-
auto *UnitContrib = IndexEntry->getContribution();
295-
if (!UnitContrib ||
296-
UnitContrib->Length != (Length + getUnitLengthFieldByteSize()))
297-
return false;
298-
auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
299-
if (!AbbrEntry)
300-
return false;
301-
AbbrOffset = AbbrEntry->Offset;
302-
}
303-
304290
// Header fields all parsed, capture the size of this unit header.
305291
assert(*offset_ptr - Offset <= 255 && "unexpected header size");
306292
Size = uint8_t(*offset_ptr - Offset);
@@ -324,6 +310,23 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
324310
return true;
325311
}
326312

313+
bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) {
314+
assert(Entry);
315+
assert(!IndexEntry);
316+
IndexEntry = Entry;
317+
if (AbbrOffset)
318+
return false;
319+
auto *UnitContrib = IndexEntry->getContribution();
320+
if (!UnitContrib ||
321+
UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize()))
322+
return false;
323+
auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
324+
if (!AbbrEntry)
325+
return false;
326+
AbbrOffset = AbbrEntry->Offset;
327+
return true;
328+
}
329+
327330
// Parse the rangelist table header, including the optional array of offsets
328331
// following it (DWARF v5 and later).
329332
template<typename ListTableType>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
## The test checks that we can read DWARFv5 type units in DWP files.
2+
3+
# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o - | \
4+
# RUN: llvm-dwarfdump -debug-info - | \
5+
# RUN: FileCheck %s
6+
7+
# CHECK: .debug_info.dwo contents:
8+
# CHECK: Type Unit:
9+
# CHECK: DW_TAG_type_unit
10+
# CHECK-NEXT: DW_AT_visibility (DW_VIS_local)
11+
# CHECK: DW_TAG_structure_type
12+
# CHECK-NEXT: DW_AT_name ("foo")
13+
14+
.section .debug_abbrev.dwo, "e", @progbits
15+
## Reserve some space in the section so that the abbreviation table for the type
16+
## unit does not start at the beginning of the section and thus the base offset
17+
## from the index section should be added to find the correct offset.
18+
.space 16
19+
.LAbbrevBegin:
20+
.uleb128 1 # Abbrev code
21+
.uleb128 0x41 # DW_TAG_type_unit
22+
.byte 1 # DW_CHILDREN_yes
23+
.uleb128 0x17 # DW_AT_visibility
24+
.uleb128 0x0b # DW_FORM_data1
25+
.byte 0 # EOM(1)
26+
.byte 0 # EOM(2)
27+
.uleb128 2 # Abbrev code
28+
.uleb128 0x13 # DW_TAG_structure_type
29+
.byte 0 # DW_CHILDREN_no
30+
.uleb128 0x03 # DW_AT_name
31+
.uleb128 0x08 # DW_FORM_string
32+
.byte 0 # EOM(1)
33+
.byte 0 # EOM(2)
34+
.byte 0 # EOM(3)
35+
.LAbbrevEnd:
36+
37+
.section .debug_info.dwo, "e", @progbits
38+
.LTUBegin:
39+
.long .LTUEnd-.LTUVersion # Length of Unit
40+
.LTUVersion:
41+
.short 5 # DWARF version number
42+
.byte 6 # DW_UT_split_type
43+
.byte 8 # Address Size (in bytes)
44+
.long 0 # Offset Into Abbrev. Section
45+
.quad 0x1100001122222222 # Type Signature
46+
.long .LTUType-.LTUBegin # Type offset
47+
.uleb128 1 # Abbrev [1] DW_TAG_type_unit
48+
.byte 1 # DW_AT_visibility
49+
.LTUType:
50+
.uleb128 2 # Abbrev [2] DW_TAG_structure_type
51+
.asciz "foo" # DW_AT_name
52+
.LTUEnd:
53+
54+
.section .debug_tu_index, "", @progbits
55+
## Header:
56+
.short 5 # Version
57+
.space 2 # Padding
58+
.long 2 # Section count
59+
.long 1 # Unit count
60+
.long 2 # Slot count
61+
## Hash Table of Signatures:
62+
.quad 0x1100001122222222
63+
.quad 0
64+
## Parallel Table of Indexes:
65+
.long 1
66+
.long 0
67+
## Table of Section Offsets:
68+
## Row 0:
69+
.long 1 # DW_SECT_INFO
70+
.long 3 # DW_SECT_ABBREV
71+
## Row 1:
72+
.long 0 # Offset in .debug_info.dwo
73+
.long .LAbbrevBegin-.debug_abbrev.dwo # Offset in .debug_abbrev.dwo
74+
## Table of Section Sizes:
75+
.long .LTUEnd-.LTUBegin # Size in .debug_info.dwo
76+
.long .LAbbrevEnd-.LAbbrevBegin # Size in .debug_abbrev.dwo

llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3166,7 +3166,7 @@ TEST(DWARFDebugInfo, TestDWARF64UnitLength) {
31663166
DWARFDataExtractor Data(Obj, Sec, /* IsLittleEndian = */ true,
31673167
/* AddressSize = */ 4);
31683168
uint64_t Offset = 0;
3169-
EXPECT_FALSE(Header.extract(*Context, Data, &Offset));
3169+
EXPECT_FALSE(Header.extract(*Context, Data, &Offset, DW_SECT_INFO));
31703170
// Header.extract() returns false because there is not enough space
31713171
// in the section for the declared length. Anyway, we can check that
31723172
// the properties are read correctly.

0 commit comments

Comments
 (0)