Skip to content

Commit

Permalink
[lldb] Fix Block::GetRangeIndexContainingAddress for discontinuous fu…
Browse files Browse the repository at this point in the history
…nctions (llvm#124931)

This is a followup to llvm#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 llvm#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).
  • Loading branch information
labath authored Feb 13, 2025
1 parent cd21e0f commit 298caeb
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 45 deletions.
53 changes: 21 additions & 32 deletions lldb/source/Symbol/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,25 +243,17 @@ bool Block::GetRangeContainingAddress(const Address &addr,
AddressRange &range) {
Function *function = CalculateSymbolContextFunction();
if (function) {
const AddressRange &func_range = function->GetAddressRange();
if (addr.GetModule() == func_range.GetBaseAddress().GetModule()) {
const addr_t file_addr = addr.GetFileAddress();
const addr_t func_file_addr =
func_range.GetBaseAddress().GetFileAddress();
if (file_addr >= func_file_addr &&
file_addr < func_file_addr + func_range.GetByteSize()) {
addr_t offset = file_addr - func_file_addr;

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

if (range_ptr) {
range.GetBaseAddress() =
Address(func_file_addr + range_ptr->GetRangeBase(),
addr.GetModule()->GetSectionList());
range.SetByteSize(range_ptr->GetByteSize());
return true;
}
}
if (uint32_t idx = GetRangeIndexContainingAddress(addr);
idx != UINT32_MAX) {
const Range *range_ptr = m_ranges.GetEntryAtIndex(idx);
assert(range_ptr);

Address func_addr = function->GetAddress();
range.GetBaseAddress() =
Address(func_addr.GetFileAddress() + range_ptr->GetRangeBase(),
func_addr.GetModule()->GetSectionList());
range.SetByteSize(range_ptr->GetByteSize());
return true;
}
}
range.Clear();
Expand All @@ -278,19 +270,16 @@ bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,

uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
Function *function = CalculateSymbolContextFunction();
if (function) {
const AddressRange &func_range = function->GetAddressRange();
if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
const addr_t addr_offset = addr.GetOffset();
const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
if (addr_offset >= func_offset &&
addr_offset < func_offset + func_range.GetByteSize()) {
addr_t offset = addr_offset - func_offset;
return m_ranges.FindEntryIndexThatContains(offset);
}
}
}
return UINT32_MAX;
if (!function)
return UINT32_MAX;

const Address &func_addr = function->GetAddress();
if (addr.GetModule() != func_addr.GetModule())
return UINT32_MAX;

const addr_t file_addr = addr.GetFileAddress();
const addr_t func_file_addr = func_addr.GetFileAddress();
return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr);
}

bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
Expand Down
39 changes: 26 additions & 13 deletions lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,24 @@

# CHECK: Found 1 function(s).
# CHECK: foo: [input.o[0x0-0xe), input.o[0x14-0x1c)]
# CHECK-NEXT: input.o[0x0]: cmpl $0x0, %edi
# CHECK-NEXT: input.o[0x3]: je 0x14
# CHECK-NEXT: input.o[0x5]: jmp 0x7
# CHECK-NEXT: input.o[0x7]: callq 0xe
# CHECK-NEXT: input.o[0xc]: jmp 0x1b
# CHECK-NEXT: input.o[0x0]: callq 0xe
# CHECK-NEXT: input.o[0x5]: jmp 0x1b
# CHECK-NEXT: input.o[0x7]: cmpl $0x0, %edi
# CHECK-NEXT: input.o[0xa]: je 0x14
# CHECK-NEXT: input.o[0xc]: jmp 0x0
# CHECK-EMPTY:
# CHECK-NEXT: input.o[0x14]: callq 0x19
# CHECK-NEXT: input.o[0x19]: jmp 0x1b
# CHECK-NEXT: input.o[0x1b]: retq
## Testing the GetRangeIndexForBlockAddress API. "ffffffff" indicates that
## the address does not belong to any range.
# CHECK-NEXT: offset 0x00 => index 0
# CHECK-NEXT: offset 0x0c => index 0
# CHECK-NEXT: offset 0x0e => index ffffffff
# CHECK-NEXT: offset 0x13 => index ffffffff
# CHECK-NEXT: offset 0x14 => index 1
# CHECK-NEXT: offset 0x1b => index 1
# CHECK-NEXT: offset 0x1c => index ffffffff


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

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

.type foo,@function
foo.__part.1:
.cfi_startproc
callq bar
jmp foo.__part.3
.Lfoo.__part.1_end:
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
.cfi_endproc

foo:
.cfi_startproc
cmpl $0, %edi
Expand All @@ -49,14 +70,6 @@ foo:
.Lfoo_end:
.size foo, .Lfoo_end-foo

foo.__part.1:
.cfi_startproc
callq bar
jmp foo.__part.3
.Lfoo.__part.1_end:
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
.cfi_endproc

bar:
.cfi_startproc
movl $47, %eax
Expand Down

0 comments on commit 298caeb

Please sign in to comment.