Skip to content

Commit 991f0fb

Browse files
committed
[DWARF] Support DWARF64 in DWARFListTableHeader.
This enables 64-bit DWARF support for parsing range and location list tables. Differential Revision: https://reviews.llvm.org/D66643 llvm-svn: 371014
1 parent e99dc4b commit 991f0fb

File tree

7 files changed

+99
-44
lines changed

7 files changed

+99
-44
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class DWARFListTableHeader {
5757
struct Header {
5858
/// The total length of the entries for this table, not including the length
5959
/// field itself.
60-
uint32_t Length = 0;
60+
uint64_t Length = 0;
6161
/// The DWARF version number.
6262
uint16_t Version;
6363
/// The size in bytes of an address on the target architecture. For
@@ -75,7 +75,7 @@ class DWARFListTableHeader {
7575
/// The offset table, which contains offsets to the individual list entries.
7676
/// It is used by forms such as DW_FORM_rnglistx.
7777
/// FIXME: Generate the table and use the appropriate forms.
78-
std::vector<uint32_t> Offsets;
78+
std::vector<uint64_t> Offsets;
7979
/// The table's format, either DWARF32 or DWARF64.
8080
dwarf::DwarfFormat Format;
8181
/// The offset at which the header (and hence the table) is located within
@@ -97,14 +97,26 @@ class DWARFListTableHeader {
9797
}
9898
uint64_t getHeaderOffset() const { return HeaderOffset; }
9999
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
100-
uint32_t getLength() const { return HeaderData.Length; }
100+
uint64_t getLength() const { return HeaderData.Length; }
101101
uint16_t getVersion() const { return HeaderData.Version; }
102102
StringRef getSectionName() const { return SectionName; }
103103
StringRef getListTypeString() const { return ListTypeString; }
104104
dwarf::DwarfFormat getFormat() const { return Format; }
105105

106+
/// Return the size of the table header including the length but not including
107+
/// the offsets.
108+
static uint8_t getHeaderSize(dwarf::DwarfFormat Format) {
109+
switch (Format) {
110+
case dwarf::DwarfFormat::DWARF32:
111+
return 12;
112+
case dwarf::DwarfFormat::DWARF64:
113+
return 20;
114+
}
115+
llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
116+
}
117+
106118
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
107-
Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
119+
Optional<uint64_t> getOffsetEntry(uint32_t Index) const {
108120
if (Index < Offsets.size())
109121
return Offsets[Index];
110122
return None;
@@ -116,7 +128,7 @@ class DWARFListTableHeader {
116128
/// Returns the length of the table, including the length field, or 0 if the
117129
/// length has not been determined (e.g. because the table has not yet been
118130
/// parsed, or there was a problem in parsing).
119-
uint32_t length() const;
131+
uint64_t length() const;
120132
};
121133

122134
/// A class representing a table of lists as specified in the DWARF v5
@@ -155,30 +167,25 @@ template <typename DWARFListType> class DWARFListTableBase {
155167

156168
uint64_t getHeaderOffset() const { return Header.getHeaderOffset(); }
157169
uint8_t getAddrSize() const { return Header.getAddrSize(); }
170+
dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
158171

159172
void dump(raw_ostream &OS,
160173
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
161174
LookupPooledAddress,
162175
DIDumpOptions DumpOpts = {}) const;
163176

164177
/// Return the contents of the offset entry designated by a given index.
165-
Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
178+
Optional<uint64_t> getOffsetEntry(uint32_t Index) const {
166179
return Header.getOffsetEntry(Index);
167180
}
168181
/// Return the size of the table header including the length but not including
169182
/// the offsets. This is dependent on the table format, which is unambiguously
170183
/// derived from parsing the table.
171184
uint8_t getHeaderSize() const {
172-
switch (Header.getFormat()) {
173-
case dwarf::DwarfFormat::DWARF32:
174-
return 12;
175-
case dwarf::DwarfFormat::DWARF64:
176-
return 20;
177-
}
178-
llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
185+
return DWARFListTableHeader::getHeaderSize(getFormat());
179186
}
180187

181-
uint32_t length() { return Header.length(); }
188+
uint64_t length() { return Header.length(); }
182189
};
183190

184191
template <typename DWARFListType>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ class DWARFUnit {
416416
/// Return a rangelist's offset based on an index. The index designates
417417
/// an entry in the rangelist table's offset array and is supplied by
418418
/// DW_FORM_rnglistx.
419-
Optional<uint32_t> getRnglistOffset(uint32_t Index) {
419+
Optional<uint64_t> getRnglistOffset(uint32_t Index) {
420420
if (RngListTable)
421421
return RngListTable->getOffsetEntry(Index);
422422
return None;

llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,34 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
2424
"section is not large enough to contain a "
2525
"%s table length at offset 0x%" PRIx64,
2626
SectionName.data(), *OffsetPtr);
27-
// TODO: Add support for DWARF64.
28-
HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
29-
if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64)
30-
return createStringError(errc::not_supported,
31-
"DWARF64 is not supported in %s at offset 0x%" PRIx64,
32-
SectionName.data(), HeaderOffset);
3327
Format = dwarf::DwarfFormat::DWARF32;
34-
if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
28+
uint8_t OffsetByteSize = 4;
29+
HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr);
30+
if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) {
31+
Format = dwarf::DwarfFormat::DWARF64;
32+
OffsetByteSize = 8;
33+
HeaderData.Length = Data.getU64(OffsetPtr);
34+
} else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) {
35+
return createStringError(errc::invalid_argument,
36+
"%s table at offset 0x%" PRIx64
37+
" has unsupported reserved unit length of value 0x%8.8" PRIx64,
38+
SectionName.data(), HeaderOffset, HeaderData.Length);
39+
}
40+
uint64_t FullLength =
41+
HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format);
42+
assert(FullLength == length());
43+
if (FullLength < getHeaderSize(Format))
3544
return createStringError(errc::invalid_argument,
3645
"%s table at offset 0x%" PRIx64
37-
" has too small length (0x%" PRIx32
46+
" has too small length (0x%" PRIx64
3847
") to contain a complete header",
39-
SectionName.data(), HeaderOffset, length());
40-
uint64_t End = HeaderOffset + length();
41-
if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
48+
SectionName.data(), HeaderOffset, FullLength);
49+
uint64_t End = HeaderOffset + FullLength;
50+
if (!Data.isValidOffsetForDataOfSize(HeaderOffset, FullLength))
4251
return createStringError(errc::invalid_argument,
4352
"section is not large enough to contain a %s table "
44-
"of length 0x%" PRIx32 " at offset 0x%" PRIx64,
45-
SectionName.data(), length(), HeaderOffset);
53+
"of length 0x%" PRIx64 " at offset 0x%" PRIx64,
54+
SectionName.data(), FullLength, HeaderOffset);
4655

4756
HeaderData.Version = Data.getU16(OffsetPtr);
4857
HeaderData.AddrSize = Data.getU8(OffsetPtr);
@@ -65,23 +74,23 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
6574
"%s table at offset 0x%" PRIx64
6675
" has unsupported segment selector size %" PRIu8,
6776
SectionName.data(), HeaderOffset, HeaderData.SegSize);
68-
if (End < HeaderOffset + sizeof(HeaderData) +
69-
HeaderData.OffsetEntryCount * sizeof(uint32_t))
77+
if (End < HeaderOffset + getHeaderSize(Format) +
78+
HeaderData.OffsetEntryCount * OffsetByteSize)
7079
return createStringError(errc::invalid_argument,
7180
"%s table at offset 0x%" PRIx64 " has more offset entries (%" PRIu32
7281
") than there is space for",
7382
SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
7483
Data.setAddressSize(HeaderData.AddrSize);
7584
for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
76-
Offsets.push_back(Data.getRelocatedValue(4, OffsetPtr));
85+
Offsets.push_back(Data.getRelocatedValue(OffsetByteSize, OffsetPtr));
7786
return Error::success();
7887
}
7988

8089
void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
8190
if (DumpOpts.Verbose)
8291
OS << format("0x%8.8" PRIx64 ": ", HeaderOffset);
8392
OS << format(
84-
"%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", "
93+
"%s list header: length = 0x%8.8" PRIx64 ", version = 0x%4.4" PRIx16 ", "
8594
"addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8
8695
", offset_entry_count = "
8796
"0x%8.8" PRIx32 "\n",
@@ -91,18 +100,17 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
91100
if (HeaderData.OffsetEntryCount > 0) {
92101
OS << "offsets: [";
93102
for (const auto &Off : Offsets) {
94-
OS << format("\n0x%8.8" PRIx32, Off);
103+
OS << format("\n0x%8.8" PRIx64, Off);
95104
if (DumpOpts.Verbose)
96105
OS << format(" => 0x%8.8" PRIx64,
97-
Off + HeaderOffset + sizeof(HeaderData));
106+
Off + HeaderOffset + getHeaderSize(Format));
98107
}
99108
OS << "\n]\n";
100109
}
101110
}
102111

103-
uint32_t DWARFListTableHeader::length() const {
112+
uint64_t DWARFListTableHeader::length() const {
104113
if (HeaderData.Length == 0)
105114
return 0;
106-
// TODO: DWARF64 support.
107-
return HeaderData.Length + sizeof(uint32_t);
115+
return HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format);
108116
}

llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_rnglists_DWARF64.s

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o - | \
2+
# RUN: llvm-dwarfdump -v --debug-rnglists - | \
3+
# RUN: FileCheck %s
4+
5+
# CHECK: .debug_rnglists contents:
6+
# CHECK-NEXT: 0x00000000: range list header:
7+
# CHECK-SAME: length = 0x0000001a,
8+
# CHECK-SAME: version = 0x0005,
9+
# CHECK-SAME: addr_size = 0x08,
10+
# CHECK-SAME: seg_size = 0x00,
11+
# CHECK-SAME: offset_entry_count = 0x00000002
12+
# CHECK-NEXT: offsets: [
13+
# CHECK-NEXT: 0x00000010 => 0x00000024
14+
# CHECK-NEXT: 0x00000011 => 0x00000025
15+
# CHECK-NEXT: ]
16+
# CHECK-NEXT: ranges:
17+
# CHECK-NEXT: 0x00000024: [DW_RLE_end_of_list]
18+
# CHECK-NEXT: 0x00000025: [DW_RLE_end_of_list]
19+
20+
.section .debug_rnglists,"",@progbits
21+
.long 0xffffffff # DWARF64 mark
22+
.quad .Lend - .Lversion # Table length
23+
.Lversion:
24+
.short 5 # Version
25+
.byte 8 # Address size
26+
.byte 0 # Segment selector size
27+
.long 2 # Offset entry count
28+
29+
.Loffsets:
30+
.quad .Ltable0 - .Loffsets
31+
.quad .Ltable1 - .Loffsets
32+
33+
.Ltable0:
34+
.byte 0 # DW_RLE_end_of_list
35+
36+
.Ltable1:
37+
.byte 0 # DW_RLE_end_of_list
38+
39+
.Lend:

llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,6 @@
3737
# CHECK-NEXT: error: section is not large enough to contain a .debug_rnglists table of length 0x1f at offset 0xe5
3838
# CHECK-NOT: error:
3939

40-
# RUN: llvm-mc %S/Inputs/debug_rnglists_DWARF64.s -filetype obj -triple x86_64-pc-linux -o - | \
41-
# RUN: llvm-dwarfdump --debug-rnglists - 2>&1 | FileCheck %s --check-prefix=DWARF64
42-
43-
# DWARF64: DWARF64 is not supported in .debug_rnglists at offset 0x0
44-
4540
.section .debug_rnglists,"",@progbits
4641

4742
# Table 1 (good)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o - | \
2+
# RUN: llvm-dwarfdump --debug-rnglists - 2>&1 | \
3+
# RUN: FileCheck %s --implicit-check-not=error
4+
5+
# CHECK: error: .debug_rnglists table at offset 0x0 has unsupported reserved unit length of value 0xfffffff0
6+
7+
.section .debug_rnglists,"",@progbits
8+
.long 0xfffffff0

0 commit comments

Comments
 (0)