Skip to content

Commit 9a6a313

Browse files
committed
[lldb] Fix block address resolution for functions in multiple sections
Continuing the theme from llvm#116777 and llvm#124931, this patch ensures we compute the correct address when a functions is spread across multiple sections. Due to this, it's not sufficient to adjust the offset in the section+offset pair (Address::Slide). We must actually slide the file offset and then recompute the section using the result.
1 parent 1563d74 commit 9a6a313

File tree

2 files changed

+123
-18
lines changed

2 files changed

+123
-18
lines changed

lldb/source/Symbol/Block.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -283,39 +283,42 @@ uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
283283
return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr);
284284
}
285285

286+
static AddressRange ToAddressRange(const Address &func_addr,
287+
const Block::Range &range) {
288+
assert(func_addr.GetModule());
289+
return AddressRange(func_addr.GetFileAddress() + range.base, range.size,
290+
func_addr.GetModule()->GetSectionList());
291+
}
292+
286293
bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
287294
if (range_idx >= m_ranges.GetSize())
288295
return false;
289296

290-
Function &function = GetFunction();
291-
const Range &vm_range = m_ranges.GetEntryRef(range_idx);
292-
range.GetBaseAddress() = function.GetAddress();
293-
range.GetBaseAddress().Slide(vm_range.GetRangeBase());
294-
range.SetByteSize(vm_range.GetByteSize());
297+
Address addr = GetFunction().GetAddress();
298+
if (!addr.GetModule())
299+
return false;
300+
301+
range = ToAddressRange(addr, m_ranges.GetEntryRef(range_idx));
295302
return true;
296303
}
297304

298305
AddressRanges Block::GetRanges() {
306+
Address addr = GetFunction().GetAddress();
307+
if (!addr.GetModule())
308+
return {};
309+
299310
AddressRanges ranges;
300-
Function &function = GetFunction();
301-
for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i) {
302-
ranges.emplace_back();
303-
auto &range = ranges.back();
304-
const Range &vm_range = m_ranges.GetEntryRef(i);
305-
range.GetBaseAddress() = function.GetAddress();
306-
range.GetBaseAddress().Slide(vm_range.GetRangeBase());
307-
range.SetByteSize(vm_range.GetByteSize());
308-
}
311+
for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i)
312+
ranges.push_back(ToAddressRange(addr, m_ranges.GetEntryRef(i)));
309313
return ranges;
310314
}
311315

312316
bool Block::GetStartAddress(Address &addr) {
313-
if (m_ranges.IsEmpty())
317+
Address func_addr = GetFunction().GetAddress();
318+
if (!func_addr.GetModule() || m_ranges.IsEmpty())
314319
return false;
315320

316-
Function &function = GetFunction();
317-
addr = function.GetAddress();
318-
addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
321+
addr = ToAddressRange(func_addr, m_ranges.GetEntryRef(0)).GetBaseAddress();
319322
return true;
320323
}
321324

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# REQUIRES: x86, lld
2+
3+
# RUN: split-file %s %t
4+
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %t/file.s -o %t/file.o
5+
# RUN: ld.lld %t/file.o -o %t/file.out -T %t/file.lds
6+
# RUN: %lldb %t/file.out -o "disassemble --name func1" -o exit | FileCheck %s
7+
8+
# CHECK: (lldb) disassemble --name func1
9+
# CHECK: file.out`func1:
10+
# CHECK-NEXT: file.out[0x0] <+0>: int $0x2a
11+
# CHECK: file.out`func1:
12+
# CHECK-NEXT: file.out[0x1000] <+4096>: int $0x2f
13+
14+
15+
#--- file.lds
16+
PHDRS {
17+
text1 PT_LOAD;
18+
text2 PT_LOAD;
19+
}
20+
SECTIONS {
21+
. = 0;
22+
.text.part1 : { *(.text.part1) } :text1
23+
.text.part2 : { *(.text.part2) } :text2
24+
}
25+
26+
#--- file.s
27+
.section .text.part1,"ax",@progbits
28+
.p2align 12
29+
func1:
30+
int $42
31+
.Lfunc1_end:
32+
33+
.section .text.part2,"ax",@progbits
34+
.p2align 12
35+
func1.__part.1:
36+
int $47
37+
.Lfunc1.__part.1_end:
38+
39+
40+
41+
.section .debug_abbrev,"",@progbits
42+
.byte 1 # Abbreviation Code
43+
.byte 17 # DW_TAG_compile_unit
44+
.byte 1 # DW_CHILDREN_yes
45+
.byte 37 # DW_AT_producer
46+
.byte 8 # DW_FORM_string
47+
.byte 19 # DW_AT_language
48+
.byte 5 # DW_FORM_data2
49+
.byte 17 # DW_AT_low_pc
50+
.byte 1 # DW_FORM_addr
51+
.byte 85 # DW_AT_ranges
52+
.byte 23 # DW_FORM_sec_offset
53+
.byte 0 # EOM(1)
54+
.byte 0 # EOM(2)
55+
.byte 2 # Abbreviation Code
56+
.byte 46 # DW_TAG_subprogram
57+
.byte 0 # DW_CHILDREN_no
58+
.byte 85 # DW_AT_ranges
59+
.byte 23 # DW_FORM_sec_offset
60+
.byte 3 # DW_AT_name
61+
.byte 8 # DW_FORM_string
62+
.byte 0 # EOM(1)
63+
.byte 0 # EOM(2)
64+
.byte 0 # EOM(3)
65+
66+
.section .debug_info,"",@progbits
67+
.Lcu_begin0:
68+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
69+
.Ldebug_info_start0:
70+
.short 5 # DWARF version number
71+
.byte 1 # DWARF Unit Type
72+
.byte 8 # Address Size (in bytes)
73+
.long .debug_abbrev # Offset Into Abbrev. Section
74+
.byte 1 # Abbrev DW_TAG_compile_unit
75+
.asciz "Hand-written DWARF" # DW_AT_producer
76+
.short 29 # DW_AT_language
77+
.quad 0 # DW_AT_low_pc
78+
.long .Ldebug_ranges0 # DW_AT_ranges
79+
.byte 2 # Abbrev DW_TAG_subprogram
80+
.long .Ldebug_ranges0 # DW_AT_ranges
81+
.asciz "func1" # DW_AT_name
82+
.byte 0 # End Of Children Mark
83+
.Ldebug_info_end0:
84+
85+
.section .debug_rnglists,"",@progbits
86+
.long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
87+
.Ldebug_list_header_start0:
88+
.short 5 # Version
89+
.byte 8 # Address size
90+
.byte 0 # Segment selector size
91+
.long 1 # Offset entry count
92+
.Lrnglists_table_base0:
93+
.long .Ldebug_ranges0-.Lrnglists_table_base0
94+
.Ldebug_ranges0:
95+
.byte 6 # DW_RLE_start_end
96+
.quad func1
97+
.quad .Lfunc1_end
98+
.byte 6 # DW_RLE_start_end
99+
.quad func1.__part.1
100+
.quad .Lfunc1.__part.1_end
101+
.byte 0 # DW_RLE_end_of_list
102+
.Ldebug_list_header_end0:

0 commit comments

Comments
 (0)