Skip to content

Commit 298caeb

Browse files
authored
[lldb] Fix Block::GetRangeIndexContainingAddress for discontinuous functions (#124931)
This is a followup to #122440, which changed function-relative calculations to use the function entry point rather than the lowest address of the function (but missed this usage). Like in #116777, the logic is changed to use file addresses instead of section offsets (as not all parts of the function have to be in the same section).
1 parent cd21e0f commit 298caeb

File tree

2 files changed

+47
-45
lines changed

2 files changed

+47
-45
lines changed

lldb/source/Symbol/Block.cpp

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,17 @@ bool Block::GetRangeContainingAddress(const Address &addr,
243243
AddressRange &range) {
244244
Function *function = CalculateSymbolContextFunction();
245245
if (function) {
246-
const AddressRange &func_range = function->GetAddressRange();
247-
if (addr.GetModule() == func_range.GetBaseAddress().GetModule()) {
248-
const addr_t file_addr = addr.GetFileAddress();
249-
const addr_t func_file_addr =
250-
func_range.GetBaseAddress().GetFileAddress();
251-
if (file_addr >= func_file_addr &&
252-
file_addr < func_file_addr + func_range.GetByteSize()) {
253-
addr_t offset = file_addr - func_file_addr;
254-
255-
const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
256-
257-
if (range_ptr) {
258-
range.GetBaseAddress() =
259-
Address(func_file_addr + range_ptr->GetRangeBase(),
260-
addr.GetModule()->GetSectionList());
261-
range.SetByteSize(range_ptr->GetByteSize());
262-
return true;
263-
}
264-
}
246+
if (uint32_t idx = GetRangeIndexContainingAddress(addr);
247+
idx != UINT32_MAX) {
248+
const Range *range_ptr = m_ranges.GetEntryAtIndex(idx);
249+
assert(range_ptr);
250+
251+
Address func_addr = function->GetAddress();
252+
range.GetBaseAddress() =
253+
Address(func_addr.GetFileAddress() + range_ptr->GetRangeBase(),
254+
func_addr.GetModule()->GetSectionList());
255+
range.SetByteSize(range_ptr->GetByteSize());
256+
return true;
265257
}
266258
}
267259
range.Clear();
@@ -278,19 +270,16 @@ bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
278270

279271
uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
280272
Function *function = CalculateSymbolContextFunction();
281-
if (function) {
282-
const AddressRange &func_range = function->GetAddressRange();
283-
if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
284-
const addr_t addr_offset = addr.GetOffset();
285-
const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
286-
if (addr_offset >= func_offset &&
287-
addr_offset < func_offset + func_range.GetByteSize()) {
288-
addr_t offset = addr_offset - func_offset;
289-
return m_ranges.FindEntryIndexThatContains(offset);
290-
}
291-
}
292-
}
293-
return UINT32_MAX;
273+
if (!function)
274+
return UINT32_MAX;
275+
276+
const Address &func_addr = function->GetAddress();
277+
if (addr.GetModule() != func_addr.GetModule())
278+
return UINT32_MAX;
279+
280+
const addr_t file_addr = addr.GetFileAddress();
281+
const addr_t func_file_addr = func_addr.GetFileAddress();
282+
return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr);
294283
}
295284

296285
bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {

lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@
66

77
# CHECK: Found 1 function(s).
88
# CHECK: foo: [input.o[0x0-0xe), input.o[0x14-0x1c)]
9-
# CHECK-NEXT: input.o[0x0]: cmpl $0x0, %edi
10-
# CHECK-NEXT: input.o[0x3]: je 0x14
11-
# CHECK-NEXT: input.o[0x5]: jmp 0x7
12-
# CHECK-NEXT: input.o[0x7]: callq 0xe
13-
# CHECK-NEXT: input.o[0xc]: jmp 0x1b
9+
# CHECK-NEXT: input.o[0x0]: callq 0xe
10+
# CHECK-NEXT: input.o[0x5]: jmp 0x1b
11+
# CHECK-NEXT: input.o[0x7]: cmpl $0x0, %edi
12+
# CHECK-NEXT: input.o[0xa]: je 0x14
13+
# CHECK-NEXT: input.o[0xc]: jmp 0x0
1414
# CHECK-EMPTY:
1515
# CHECK-NEXT: input.o[0x14]: callq 0x19
1616
# CHECK-NEXT: input.o[0x19]: jmp 0x1b
1717
# CHECK-NEXT: input.o[0x1b]: retq
18+
## Testing the GetRangeIndexForBlockAddress API. "ffffffff" indicates that
19+
## the address does not belong to any range.
20+
# CHECK-NEXT: offset 0x00 => index 0
21+
# CHECK-NEXT: offset 0x0c => index 0
22+
# CHECK-NEXT: offset 0x0e => index ffffffff
23+
# CHECK-NEXT: offset 0x13 => index ffffffff
24+
# CHECK-NEXT: offset 0x14 => index 1
25+
# CHECK-NEXT: offset 0x1b => index 1
26+
# CHECK-NEXT: offset 0x1c => index ffffffff
1827

1928

2029
#--- script.py
@@ -28,6 +37,10 @@ def __lldb_init_module(debugger, internal_dict):
2837
fn = ctx.function
2938
print(f"{fn.name}: {fn.GetRanges()}")
3039
print(fn.GetInstructions(target))
40+
text = fn.addr.section
41+
for offset in [0x00, 0x0c, 0x0e, 0x13, 0x14, 0x1b, 0x1c]:
42+
idx = fn.block.GetRangeIndexForBlockAddress(lldb.SBAddress(text, offset))
43+
print(f"offset 0x{offset:02x} => index {idx:x}")
3144

3245
#--- input.s
3346
# An example of a function which has been split into two parts. Roughly
@@ -40,6 +53,14 @@ def __lldb_init_module(debugger, internal_dict):
4053
.text
4154

4255
.type foo,@function
56+
foo.__part.1:
57+
.cfi_startproc
58+
callq bar
59+
jmp foo.__part.3
60+
.Lfoo.__part.1_end:
61+
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
62+
.cfi_endproc
63+
4364
foo:
4465
.cfi_startproc
4566
cmpl $0, %edi
@@ -49,14 +70,6 @@ foo:
4970
.Lfoo_end:
5071
.size foo, .Lfoo_end-foo
5172

52-
foo.__part.1:
53-
.cfi_startproc
54-
callq bar
55-
jmp foo.__part.3
56-
.Lfoo.__part.1_end:
57-
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
58-
.cfi_endproc
59-
6073
bar:
6174
.cfi_startproc
6275
movl $47, %eax

0 commit comments

Comments
 (0)