Skip to content

Commit 5afc153

Browse files
author
George Rimar
committed
[DebugInfo] - Fix for lld DWARF parsing of base address selection entries in range lists.
It solves issue of wrong section index evaluating for ranges when base address is used. Based on David Blaikie's patch D36097. Differential revision: https://reviews.llvm.org/D37214 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312477 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 228d11f commit 5afc153

File tree

8 files changed

+133
-16
lines changed

8 files changed

+133
-16
lines changed

include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
namespace llvm {
2020

21+
struct BaseAddress;
2122
class raw_ostream;
2223

2324
struct DWARFAddressRange {
@@ -85,7 +86,8 @@ class DWARFDebugRangeList {
8586
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
8687
/// list. Has to be passed base address of the compile unit referencing this
8788
/// range list.
88-
DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
89+
DWARFAddressRangesVector
90+
getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
8991
};
9092

9193
} // end namespace llvm

include/llvm/DebugInfo/DWARF/DWARFUnit.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
110110
}
111111
};
112112

113+
/// Represents base address of the CU.
114+
struct BaseAddress {
115+
uint64_t Address;
116+
uint64_t SectionIndex;
117+
};
118+
113119
class DWARFUnit {
114120
DWARFContext &Context;
115121
/// Section containing this DWARFUnit.
@@ -135,7 +141,7 @@ class DWARFUnit {
135141
uint32_t Length;
136142
const DWARFAbbreviationDeclarationSet *Abbrevs;
137143
uint8_t UnitType;
138-
uint64_t BaseAddr;
144+
llvm::Optional<BaseAddress> BaseAddr;
139145
/// The compile unit debug information entry items.
140146
std::vector<DWARFDebugInfoEntry> DieArray;
141147

@@ -259,11 +265,9 @@ class DWARFUnit {
259265
llvm_unreachable("Invalid UnitType.");
260266
}
261267

262-
uint64_t getBaseAddress() const { return BaseAddr; }
268+
llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
263269

264-
void setBaseAddress(uint64_t base_addr) {
265-
BaseAddr = base_addr;
266-
}
270+
void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
267271

268272
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
269273
extractDIEsIfNeeded(ExtractUnitDIEOnly);

lib/DebugInfo/DWARF/DWARFDataExtractor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ using namespace llvm;
1414

1515
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
1616
uint64_t *SecNdx) const {
17+
if (SecNdx)
18+
*SecNdx = -1ULL;
1719
if (!Section)
1820
return getUnsigned(Off, Size);
1921
Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);

lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,29 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
6363
OS << format("%08x <End of list>\n", Offset);
6464
}
6565

66-
DWARFAddressRangesVector
67-
DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
66+
DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
67+
llvm::Optional<BaseAddress> BaseAddr) const {
6868
DWARFAddressRangesVector Res;
6969
for (const RangeListEntry &RLE : Entries) {
7070
if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
71-
BaseAddress = RLE.EndAddress;
72-
} else {
73-
Res.push_back({BaseAddress + RLE.StartAddress,
74-
BaseAddress + RLE.EndAddress, RLE.SectionIndex});
71+
BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
72+
continue;
7573
}
74+
75+
DWARFAddressRange E;
76+
E.LowPC = RLE.StartAddress;
77+
E.HighPC = RLE.EndAddress;
78+
E.SectionIndex = RLE.SectionIndex;
79+
// Base address of a range list entry is determined by the closest preceding
80+
// base address selection entry in the same range list. It defaults to the
81+
// base address of the compilation unit if there is no such entry.
82+
if (BaseAddr) {
83+
E.LowPC += BaseAddr->Address;
84+
E.HighPC += BaseAddr->Address;
85+
if (E.SectionIndex == -1ULL)
86+
E.SectionIndex = BaseAddr->SectionIndex;
87+
}
88+
Res.push_back(E);
7689
}
7790
return Res;
7891
}

lib/DebugInfo/DWARF/DWARFUnit.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ void DWARFUnit::clear() {
160160
Length = 0;
161161
Abbrevs = nullptr;
162162
FormParams = DWARFFormParams({0, 0, DWARF32});
163-
BaseAddr = 0;
163+
BaseAddr.reset();
164164
RangeSectionBase = 0;
165165
AddrOffsetSectionBase = 0;
166166
clearDIEs(false);
@@ -242,9 +242,10 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
242242
// If CU DIE was just parsed, copy several attribute values from it.
243243
if (!HasCUDie) {
244244
DWARFDie UnitDie = getUnitDIE();
245-
auto BaseAddr = toAddress(UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}));
246-
if (BaseAddr)
247-
setBaseAddress(*BaseAddr);
245+
Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
246+
if (Optional<uint64_t> Addr = toAddress(PC))
247+
setBaseAddress({*Addr, PC->getSectionIndex()});
248+
248249
if (!isDWO) {
249250
assert(AddrOffsetSectionBase == 0);
250251
assert(RangeSectionBase == 0);
Binary file not shown.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# RUN: llvm-dwarfdump %S/../Inputs/dwarfdump-ranges-baseaddr-exe.elf-x86-64 \
2+
# RUN: | FileCheck %s
3+
4+
## Executable binary for test produced from object built in
5+
## dwarfdump-ranges-baseaddr.s testcase.
6+
7+
# CHECK: .debug_info contents:
8+
# CHECK: 0x0000000b: DW_TAG_compile_unit [1]
9+
# CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000400078)
10+
# CHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
11+
# CHECK-NEXT: [0x0000000000400078 - 0x0000000000400079)
12+
# CHECK-NEXT: [0x000000000040007b - 0x000000000040007e)
13+
# CHECK-NEXT: [0x000000000040007f - 0x0000000000400080))
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
2+
# RUN: llvm-dwarfdump %t | FileCheck %s
3+
4+
# CHECK: .debug_info contents:
5+
# CHECK: 0x0000000b: DW_TAG_compile_unit [1]
6+
# CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
7+
# CHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
8+
# CHECK-NEXT: [0x0000000000000000 - 0x0000000000000001) ".text"
9+
# CHECK-NEXT: [0x0000000000000003 - 0x0000000000000006) ".text"
10+
# CHECK-NEXT: [0x0000000000000001 - 0x0000000000000002) ".text.foo1")
11+
12+
.text
13+
.globl foo
14+
.type foo,@function
15+
foo:
16+
.Lfunc_begin0:
17+
nop
18+
.Ltmp0:
19+
nop
20+
nop
21+
.Ltmp1:
22+
nop
23+
nop
24+
nop
25+
.Ltmp2:
26+
27+
.section .text.foo1,"ax",@progbits
28+
.Ltmp3:
29+
nop
30+
.Ltmp4:
31+
nop
32+
.Ltmp5:
33+
34+
.section .debug_abbrev,"",@progbits
35+
.byte 1 # Abbreviation Code
36+
.byte 17 # DW_TAG_compile_unit
37+
.byte 0 # DW_CHILDREN_no
38+
.byte 37 # DW_AT_producer
39+
.byte 14 # DW_FORM_strp
40+
.byte 19 # DW_AT_language
41+
.byte 5 # DW_FORM_data2
42+
.byte 3 # DW_AT_name
43+
.byte 14 # DW_FORM_strp
44+
.byte 16 # DW_AT_stmt_list
45+
.byte 23 # DW_FORM_sec_offset
46+
.byte 27 # DW_AT_comp_dir
47+
.byte 14 # DW_FORM_strp
48+
.byte 17 # DW_AT_low_pc
49+
.byte 1 # DW_FORM_addr
50+
.byte 85 # DW_AT_ranges
51+
.byte 23 # DW_FORM_sec_offset
52+
.byte 0 # EOM(1)
53+
.byte 0 # EOM(2)
54+
.byte 0 # EOM(3)
55+
56+
.section .debug_info,"",@progbits
57+
.Lcu_begin0:
58+
.long 38 # Length of Unit
59+
.short 4 # DWARF version number
60+
.long .debug_abbrev # Offset Into Abbrev. Section
61+
.byte 8 # Address Size (in bytes)
62+
.byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
63+
.long 0 # DW_AT_producer
64+
.short 4 # DW_AT_language
65+
.long 0 # DW_AT_name
66+
.long 0 # DW_AT_stmt_list
67+
.long 0 # DW_AT_comp_dir
68+
.quad .Lfunc_begin0 # DW_AT_low_pc
69+
.long .Ldebug_ranges0 # DW_AT_ranges
70+
71+
.section .debug_ranges,"",@progbits
72+
.Ldebug_ranges0:
73+
.quad .Lfunc_begin0-.Lfunc_begin0
74+
.quad .Ltmp0-.Lfunc_begin0
75+
.quad .Ltmp1-.Lfunc_begin0
76+
.quad .Ltmp2-.Lfunc_begin0
77+
.quad 0xFFFFFFFFFFFFFFFF
78+
.quad .text.foo1
79+
.quad .Ltmp4-.text.foo1
80+
.quad .Ltmp5-.text.foo1
81+
.quad 0
82+
.quad 0

0 commit comments

Comments
 (0)