Skip to content

Commit 57b4898

Browse files
authored
[lldb] Use the first address range as the function address (#122440)
This is the behavior expected by DWARF. It also requires some fixups to algorithms which were storing the addresses of some objects (Blocks and Variables) relative to the beginning of the function. There are plenty of things that still don't work in this setups, but this change is sufficient for the expression evaluator to correctly recognize the entry point of a function in this case.
1 parent b60c118 commit 57b4898

File tree

11 files changed

+65
-47
lines changed

11 files changed

+65
-47
lines changed

lldb/include/lldb/Symbol/Function.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ class Function : public UserID, public SymbolContextScope {
428428
/// The section offset based address for this function.
429429
Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
430430
lldb::user_id_t func_type_uid, const Mangled &mangled,
431-
Type *func_type, AddressRanges ranges);
431+
Type *func_type, Address address, AddressRanges ranges);
432432

433433
/// Destructor.
434434
~Function() override;

lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,11 @@ FunctionSP SymbolFileBreakpad::GetOrCreateFunction(CompileUnit &comp_unit) {
251251
addr_t address = record->Address + base;
252252
SectionSP section_sp = list->FindSectionContainingFileAddress(address);
253253
if (section_sp) {
254-
AddressRange func_range(
255-
section_sp, address - section_sp->GetFileAddress(), record->Size);
254+
Address func_addr(section_sp, address - section_sp->GetFileAddress());
256255
// Use the CU's id because every CU has only one function inside.
257-
func_sp = std::make_shared<Function>(&comp_unit, id, 0, func_name,
258-
nullptr, AddressRanges{func_range});
256+
func_sp = std::make_shared<Function>(
257+
&comp_unit, id, 0, func_name, nullptr, func_addr,
258+
AddressRanges{AddressRange(func_addr, record->Size)});
259259
comp_unit.AddFunction(func_sp);
260260
}
261261
}

lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) {
829829
lldb::user_id_t func_uid = m_functions.size();
830830
FunctionSP function_sp = std::make_shared<Function>(
831831
&cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(),
832-
AddressRanges{func_range});
832+
symbol->GetAddress(), AddressRanges{func_range});
833833
m_functions.emplace_back(function_sp);
834834
cu.AddFunction(function_sp);
835835
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2462,10 +2462,29 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(
24622462
assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
24632463

24642464
const user_id_t func_user_id = die.GetID();
2465+
2466+
// The base address of the scope for any of the debugging information
2467+
// entries listed above is given by either the DW_AT_low_pc attribute or the
2468+
// first address in the first range entry in the list of ranges given by the
2469+
// DW_AT_ranges attribute.
2470+
// -- DWARFv5, Section 2.17 Code Addresses, Ranges and Base Addresses
2471+
//
2472+
// If no DW_AT_entry_pc attribute is present, then the entry address is
2473+
// assumed to be the same as the base address of the containing scope.
2474+
// -- DWARFv5, Section 2.18 Entry Address
2475+
//
2476+
// We currently don't support Debug Info Entries with
2477+
// DW_AT_low_pc/DW_AT_entry_pc and DW_AT_ranges attributes (the latter
2478+
// attributes are ignored even though they should be used for the address of
2479+
// the function), but compilers also don't emit that kind of information. If
2480+
// this becomes a problem we need to plumb these attributes separately.
2481+
Address func_addr = func_ranges[0].GetBaseAddress();
2482+
24652483
func_sp = std::make_shared<Function>(
24662484
&comp_unit,
24672485
func_user_id, // UserID is the DIE offset
2468-
func_user_id, func_name, func_type, std::move(func_ranges));
2486+
func_user_id, func_name, func_type, std::move(func_addr),
2487+
std::move(func_ranges));
24692488

24702489
if (func_sp.get() != nullptr) {
24712490
if (frame_base.IsValid())

lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,9 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
263263
}
264264

265265
if (set_frame_base_loclist_addr && !ranges.empty()) {
266-
// TODO: Use the first range instead.
267-
dw_addr_t lowest_range_pc = llvm::min_element(ranges)->LowPC;
268-
assert(lowest_range_pc >= cu->GetBaseAddress());
269-
frame_base->SetFuncFileAddress(lowest_range_pc);
266+
dw_addr_t file_addr = ranges.begin()->LowPC;
267+
assert(file_addr >= cu->GetBaseAddress());
268+
frame_base->SetFuncFileAddress(file_addr);
270269
}
271270

272271
if (ranges.empty() || name == nullptr || mangled == nullptr) {

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3174,8 +3174,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) {
31743174
/*check_hi_lo_pc=*/true)) {
31753175
if (ranges->empty())
31763176
return 0;
3177-
// TODO: Use the first range instead.
3178-
dw_addr_t function_file_addr = llvm::min_element(*ranges)->LowPC;
3177+
dw_addr_t function_file_addr = ranges->begin()->LowPC;
31793178
if (function_file_addr != LLDB_INVALID_ADDRESS)
31803179
ParseBlocksRecursive(*comp_unit, &func.GetBlock(false),
31813180
function_die.GetFirstChild(), function_file_addr);
@@ -3214,9 +3213,8 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
32143213
if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
32153214
function_die.GetDIE()->GetAttributeAddressRanges(
32163215
function_die.GetCU(), /*check_hi_lo_pc=*/true)) {
3217-
// TODO: Use the first range element instead.
32183216
if (!ranges->empty())
3219-
func_lo_pc = llvm::min_element(*ranges)->LowPC;
3217+
func_lo_pc = ranges->begin()->LowPC;
32203218
} else {
32213219
LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(),
32223220
"DIE({1:x}): {0}", function_die.GetID());

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -483,9 +483,8 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
483483
if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
484484
return nullptr;
485485

486-
AddressRange func_range(file_vm_addr, sol.length,
487-
comp_unit.GetModule()->GetSectionList());
488-
if (!func_range.GetBaseAddress().IsValid())
486+
Address func_addr(file_vm_addr, comp_unit.GetModule()->GetSectionList());
487+
if (!func_addr.IsValid())
489488
return nullptr;
490489

491490
ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
@@ -500,7 +499,8 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
500499
Mangled mangled(proc.Name);
501500
FunctionSP func_sp = std::make_shared<Function>(
502501
&comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
503-
func_type.get(), AddressRanges{func_range});
502+
func_type.get(), func_addr,
503+
AddressRanges{AddressRange(func_addr, sol.length)});
504504

505505
comp_unit.AddFunction(func_sp);
506506

@@ -1279,9 +1279,7 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
12791279
if (file_vm_addr == LLDB_INVALID_ADDRESS)
12801280
continue;
12811281

1282-
AddressRange func_range(file_vm_addr, sol.length,
1283-
comp_unit.GetModule()->GetSectionList());
1284-
Address func_base = func_range.GetBaseAddress();
1282+
Address func_base(file_vm_addr, comp_unit.GetModule()->GetSectionList());
12851283
PdbCompilandSymId func_id{modi, record_offset};
12861284

12871285
// Iterate all S_INLINESITEs in the function.

lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,9 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func,
296296
return nullptr;
297297

298298
auto func_length = pdb_func.getLength();
299-
AddressRange func_range =
300-
AddressRange(file_vm_addr, func_length,
301-
GetObjectFile()->GetModule()->GetSectionList());
302-
if (!func_range.GetBaseAddress().IsValid())
299+
Address func_addr(file_vm_addr,
300+
GetObjectFile()->GetModule()->GetSectionList());
301+
if (!func_addr.IsValid())
303302
return nullptr;
304303

305304
lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
@@ -312,7 +311,7 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func,
312311

313312
FunctionSP func_sp = std::make_shared<Function>(
314313
&comp_unit, pdb_func.getSymIndexId(), func_type_uid, mangled, func_type,
315-
AddressRanges{func_range});
314+
func_addr, AddressRanges{AddressRange(func_addr, func_length)});
316315

317316
comp_unit.AddFunction(func_sp);
318317

lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) {
179179
}
180180
}
181181

182-
FunctionSP func_sp(
183-
new Function(&comp_unit,
184-
symbol_idx, // UserID is the DIE offset
185-
LLDB_INVALID_UID, // We don't have any type info
186-
// for this function
187-
curr_symbol->GetMangled(), // Linker/mangled name
188-
nullptr, // no return type for a code symbol...
189-
AddressRanges{func_range}));
182+
FunctionSP func_sp(new Function(
183+
&comp_unit,
184+
symbol_idx, // UserID is the DIE offset
185+
LLDB_INVALID_UID, // We don't have any type info
186+
// for this function
187+
curr_symbol->GetMangled(), // Linker/mangled name
188+
nullptr, // no return type for a code symbol...
189+
curr_symbol->GetAddress(), AddressRanges{func_range}));
190190

191191
if (func_sp.get() != nullptr) {
192192
comp_unit.AddFunction(func_sp);

lldb/source/Symbol/Function.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ AddressRange CollapseRanges(llvm::ArrayRef<AddressRange> ranges) {
276276
//
277277
Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
278278
lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
279-
AddressRanges ranges)
279+
Address address, AddressRanges ranges)
280280
: UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid),
281281
m_type(type), m_mangled(mangled), m_block(*this, func_uid),
282-
m_range(CollapseRanges(ranges)), m_address(m_range.GetBaseAddress()),
282+
m_range(CollapseRanges(ranges)), m_address(std::move(address)),
283283
m_prologue_byte_size(0) {
284284
assert(comp_unit != nullptr);
285285
lldb::addr_t base_file_addr = m_address.GetFileAddress();

lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,30 @@
33
# int baz();
44
# int bar() { return 47; }
55
# int foo(int flag) { return flag ? bar() : baz(); }
6-
# The function bar has been placed "in the middle" of foo.
6+
# The function bar has been placed "in the middle" of foo, and the function
7+
# entry point is deliberately not its lowest address.
78

89
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
9-
# RUN: %lldb %t -o "image lookup -v -n foo" -o exit | FileCheck %s
10+
# RUN: %lldb %t -o "image lookup -v -n foo" -o "expr -- &foo" -o exit | FileCheck %s
1011

12+
# CHECK-LABEL: image lookup
1113
# CHECK: 1 match found in {{.*}}
1214
# CHECK: Summary: {{.*}}`foo
1315
# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x0000000000000000-0x000000000000000e)[0x0000000000000014-0x000000000000001c)
1416

17+
# CHECK-LABEL: expr -- &foo
18+
# CHECK: (void (*)()) $0 = 0x0000000000000007
19+
1520
.text
1621

22+
foo.__part.1:
23+
.cfi_startproc
24+
callq bar
25+
jmp foo.__part.3
26+
.Lfoo.__part.1_end:
27+
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
28+
.cfi_endproc
29+
1730
.type foo,@function
1831
foo:
1932
.cfi_startproc
@@ -24,14 +37,6 @@ foo:
2437
.Lfoo_end:
2538
.size foo, .Lfoo_end-foo
2639

27-
foo.__part.1:
28-
.cfi_startproc
29-
callq bar
30-
jmp foo.__part.3
31-
.Lfoo.__part.1_end:
32-
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
33-
.cfi_endproc
34-
3540
bar:
3641
.cfi_startproc
3742
movl $47, %eax

0 commit comments

Comments
 (0)