Skip to content

Commit d71fa33

Browse files
authored
[lldb] Fix inline function resolution for discontinuous functions (llvm#116777)
The problem here is the assumption that the entire function will be placed in a single section. This will ~never be the case for a discontinuous function, as the point of splitting the function is to let the linker group parts of the function according to their "hotness". The fix is to change the offset computation to use file addresses instead.
1 parent 1490f38 commit d71fa33

File tree

3 files changed

+183
-13
lines changed

3 files changed

+183
-13
lines changed

lldb/source/Symbol/Block.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,19 +252,20 @@ bool Block::GetRangeContainingAddress(const Address &addr,
252252
Function *function = CalculateSymbolContextFunction();
253253
if (function) {
254254
const AddressRange &func_range = function->GetAddressRange();
255-
if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
256-
const addr_t addr_offset = addr.GetOffset();
257-
const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
258-
if (addr_offset >= func_offset &&
259-
addr_offset < func_offset + func_range.GetByteSize()) {
260-
addr_t offset = addr_offset - func_offset;
255+
if (addr.GetModule() == func_range.GetBaseAddress().GetModule()) {
256+
const addr_t file_addr = addr.GetFileAddress();
257+
const addr_t func_file_addr =
258+
func_range.GetBaseAddress().GetFileAddress();
259+
if (file_addr >= func_file_addr &&
260+
file_addr < func_file_addr + func_range.GetByteSize()) {
261+
addr_t offset = file_addr - func_file_addr;
261262

262263
const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
263264

264265
if (range_ptr) {
265-
range.GetBaseAddress() = func_range.GetBaseAddress();
266-
range.GetBaseAddress().SetOffset(func_offset +
267-
range_ptr->GetRangeBase());
266+
range.GetBaseAddress() =
267+
Address(func_file_addr + range_ptr->GetRangeBase(),
268+
addr.GetModule()->GetSectionList());
268269
range.SetByteSize(range_ptr->GetByteSize());
269270
return true;
270271
}

lldb/source/Symbol/SymbolContext.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,11 @@ bool SymbolContext::DumpStopContext(
102102
s->PutCStringColorHighlighted(name.GetStringRef(), settings);
103103
}
104104

105-
if (addr.IsValid()) {
105+
if (addr_t file_addr = addr.GetFileAddress();
106+
file_addr != LLDB_INVALID_ADDRESS) {
106107
const addr_t function_offset =
107-
addr.GetOffset() -
108-
function->GetAddressRange().GetBaseAddress().GetOffset();
108+
file_addr -
109+
function->GetAddressRange().GetBaseAddress().GetFileAddress();
109110
if (!show_function_name) {
110111
// Print +offset even if offset is 0
111112
dumped_something = true;
@@ -126,7 +127,8 @@ bool SymbolContext::DumpStopContext(
126127
lldb_private::AddressRange block_range;
127128
if (inlined_block->GetRangeContainingAddress(addr, block_range)) {
128129
const addr_t inlined_function_offset =
129-
addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
130+
addr.GetFileAddress() -
131+
block_range.GetBaseAddress().GetFileAddress();
130132
if (inlined_function_offset) {
131133
s->Printf(" + %" PRIu64, inlined_function_offset);
132134
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
## Test that inline function resolution works when the function has been split
2+
## into multiple discontinuous parts (and those parts are placed in different
3+
## sections)
4+
5+
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
6+
# RUN: %lldb %t -o "image lookup -v -n look_me_up" -o exit | FileCheck %s
7+
8+
# CHECK: 1 match found in {{.*}}
9+
# CHECK: Summary: {{.*}}`foo + 6 [inlined] foo_inl + 1
10+
# CHECK-NEXT: {{.*}}`foo + 5
11+
# CHECK: Blocks: id = {{.*}}, ranges = [0x00000000-0x00000003)[0x00000004-0x00000008)
12+
# CHECK-NEXT: id = {{.*}}, ranges = [0x00000001-0x00000002)[0x00000005-0x00000007), name = "foo_inl"
13+
14+
.text
15+
16+
.type foo,@function
17+
foo:
18+
nop
19+
.Lfoo_inl:
20+
nop
21+
.Lfoo_inl_end:
22+
nop
23+
.Lfoo_end:
24+
.size foo, .Lfoo_end-foo
25+
26+
bar:
27+
nop
28+
.Lbar_end:
29+
.size bar, .Lbar_end-bar
30+
31+
.section .text.__part1,"ax",@progbits
32+
foo.__part.1:
33+
nop
34+
.Lfoo_inl.__part.1:
35+
nop
36+
.type look_me_up,@function
37+
look_me_up:
38+
nop
39+
.Lfoo_inl.__part.1_end:
40+
nop
41+
.Lfoo.__part.1_end:
42+
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
43+
44+
45+
.section .debug_abbrev,"",@progbits
46+
.byte 1 # Abbreviation Code
47+
.byte 17 # DW_TAG_compile_unit
48+
.byte 1 # DW_CHILDREN_yes
49+
.byte 37 # DW_AT_producer
50+
.byte 8 # DW_FORM_string
51+
.byte 19 # DW_AT_language
52+
.byte 5 # DW_FORM_data2
53+
.byte 17 # DW_AT_low_pc
54+
.byte 1 # DW_FORM_addr
55+
.byte 85 # DW_AT_ranges
56+
.byte 35 # DW_FORM_rnglistx
57+
.byte 116 # DW_AT_rnglists_base
58+
.byte 23 # DW_FORM_sec_offset
59+
.byte 0 # EOM(1)
60+
.byte 0 # EOM(2)
61+
.byte 2 # Abbreviation Code
62+
.byte 46 # DW_TAG_subprogram
63+
.byte 0 # DW_CHILDREN_no
64+
.byte 3 # DW_AT_name
65+
.byte 8 # DW_FORM_string
66+
.byte 0 # EOM(1)
67+
.byte 0 # EOM(2)
68+
.byte 3 # Abbreviation Code
69+
.byte 46 # DW_TAG_subprogram
70+
.byte 1 # DW_CHILDREN_yes
71+
.byte 85 # DW_AT_ranges
72+
.byte 35 # DW_FORM_rnglistx
73+
.byte 3 # DW_AT_name
74+
.byte 8 # DW_FORM_string
75+
.byte 0 # EOM(1)
76+
.byte 0 # EOM(2)
77+
.byte 4 # Abbreviation Code
78+
.byte 29 # DW_TAG_inlined_subroutine
79+
.byte 0 # DW_CHILDREN_no
80+
.byte 85 # DW_AT_ranges
81+
.byte 35 # DW_FORM_rnglistx
82+
.byte 49 # DW_AT_abstract_origin
83+
.byte 19 # DW_FORM_ref4
84+
.byte 0 # EOM(1)
85+
.byte 0 # EOM(2)
86+
.byte 0 # EOM(3)
87+
88+
.section .debug_info,"",@progbits
89+
.Lcu_begin0:
90+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
91+
.Ldebug_info_start0:
92+
.short 5 # DWARF version number
93+
.byte 1 # DWARF Unit Type
94+
.byte 8 # Address Size (in bytes)
95+
.long .debug_abbrev # Offset Into Abbrev. Section
96+
.byte 1 # Abbrev DW_TAG_compile_unit
97+
.asciz "Hand-written DWARF" # DW_AT_producer
98+
.short 29 # DW_AT_language
99+
.quad 0 # DW_AT_low_pc
100+
.byte 1 # DW_AT_ranges
101+
.long .Lrnglists_table_base0 # DW_AT_rnglists_base
102+
103+
.byte 3 # Abbrev DW_TAG_subprogram
104+
.byte 2 # DW_AT_ranges
105+
.asciz "bar" # DW_AT_name
106+
.byte 0 # End Of Children Mark
107+
108+
.Lfoo_inl_die:
109+
.byte 2 # Abbrev DW_TAG_subprogram
110+
.asciz "foo_inl" # DW_AT_name
111+
112+
.byte 3 # Abbrev DW_TAG_subprogram
113+
.byte 0 # DW_AT_ranges
114+
.asciz "foo" # DW_AT_name
115+
.byte 4 # Abbrev DW_TAG_inlined_subroutine
116+
.byte 3 # DW_AT_ranges
117+
.long .Lfoo_inl_die-.Lcu_begin0 # DW_AT_abstract_origin
118+
.byte 0 # End Of Children Mark
119+
120+
.byte 0 # End Of Children Mark
121+
.Ldebug_info_end0:
122+
123+
.section .debug_rnglists,"",@progbits
124+
.long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
125+
.Ldebug_list_header_start0:
126+
.short 5 # Version
127+
.byte 8 # Address size
128+
.byte 0 # Segment selector size
129+
.long 4 # Offset entry count
130+
.Lrnglists_table_base0:
131+
.long .Ldebug_ranges0-.Lrnglists_table_base0
132+
.long .Ldebug_ranges1-.Lrnglists_table_base0
133+
.long .Ldebug_ranges2-.Lrnglists_table_base0
134+
.long .Ldebug_ranges3-.Lrnglists_table_base0
135+
.Ldebug_ranges0:
136+
.byte 6 # DW_RLE_start_end
137+
.quad foo
138+
.quad .Lfoo_end
139+
.byte 6 # DW_RLE_start_end
140+
.quad foo.__part.1
141+
.quad .Lfoo.__part.1_end
142+
.byte 0 # DW_RLE_end_of_list
143+
.Ldebug_ranges1:
144+
.byte 6 # DW_RLE_start_end
145+
.quad bar
146+
.quad .Lbar_end
147+
.byte 6 # DW_RLE_start_end
148+
.quad foo.__part.1
149+
.quad .Lfoo.__part.1_end
150+
.byte 6 # DW_RLE_start_end
151+
.quad foo
152+
.quad .Lfoo_end
153+
.byte 0 # DW_RLE_end_of_list
154+
.Ldebug_ranges2:
155+
.byte 6 # DW_RLE_start_end
156+
.quad bar
157+
.quad .Lbar_end
158+
.byte 0 # DW_RLE_end_of_list
159+
.Ldebug_ranges3:
160+
.byte 6 # DW_RLE_start_end
161+
.quad .Lfoo_inl
162+
.quad .Lfoo_inl_end
163+
.byte 6 # DW_RLE_start_end
164+
.quad .Lfoo_inl.__part.1
165+
.quad .Lfoo_inl.__part.1_end
166+
.byte 0 # DW_RLE_end_of_list
167+
.Ldebug_list_header_end0:

0 commit comments

Comments
 (0)