Skip to content

Commit 112b896

Browse files
author
git apple-llvm automerger
committed
Merge commit 'd865f32fe820' from llvm.org/main into next
2 parents f31a0b9 + d865f32 commit 112b896

File tree

8 files changed

+131
-114
lines changed

8 files changed

+131
-114
lines changed

lldb/include/lldb/Symbol/DWARFCallFrameInfo.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ class DWARFCallFrameInfo {
4747
/// Return an UnwindPlan based on the call frame information encoded in the
4848
/// FDE of this DWARFCallFrameInfo section. The returned plan will be valid
4949
/// (at least) for the given address.
50-
bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan);
50+
std::unique_ptr<UnwindPlan> GetUnwindPlan(const Address &addr);
5151

5252
/// Return an UnwindPlan based on the call frame information encoded in the
5353
/// FDE of this DWARFCallFrameInfo section. The returned plan will be valid
54-
/// (at least) for some address in the given range.
55-
bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan);
54+
/// (at least) for some address in the given ranges. If no unwind information
55+
/// is found, nullptr is returned. \a addr represents the entry point of the
56+
/// function. It corresponds to the offset zero in the returned UnwindPlan.
57+
std::unique_ptr<UnwindPlan> GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges,
58+
const Address &addr);
5659

5760
typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector;
5861

lldb/source/Symbol/DWARFCallFrameInfo.cpp

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -151,53 +151,57 @@ DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,
151151
SectionSP &section_sp, Type type)
152152
: m_objfile(objfile), m_section_sp(section_sp), m_type(type) {}
153153

154-
bool DWARFCallFrameInfo::GetUnwindPlan(const Address &addr,
155-
UnwindPlan &unwind_plan) {
156-
return GetUnwindPlan(AddressRange(addr, 1), unwind_plan);
154+
std::unique_ptr<UnwindPlan>
155+
DWARFCallFrameInfo::GetUnwindPlan(const Address &addr) {
156+
return GetUnwindPlan({AddressRange(addr, 1)}, addr);
157157
}
158158

159-
bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange &range,
160-
UnwindPlan &unwind_plan) {
159+
std::unique_ptr<UnwindPlan>
160+
DWARFCallFrameInfo::GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges,
161+
const Address &addr) {
161162
FDEEntryMap::Entry fde_entry;
162-
Address addr = range.GetBaseAddress();
163163

164164
// Make sure that the Address we're searching for is the same object file as
165165
// this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
166166
ModuleSP module_sp = addr.GetModule();
167167
if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
168168
module_sp->GetObjectFile() != &m_objfile)
169-
return false;
169+
return nullptr;
170170

171-
std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range);
172-
if (!entry)
173-
return false;
171+
std::vector<AddressRange> valid_ranges;
174172

175-
std::optional<FDE> fde = ParseFDE(entry->data, addr);
176-
if (!fde)
177-
return false;
178-
179-
unwind_plan.SetSourceName(m_type == EH ? "eh_frame CFI" : "DWARF CFI");
173+
auto result = std::make_unique<UnwindPlan>(GetRegisterKind());
174+
result->SetSourceName(m_type == EH ? "eh_frame CFI" : "DWARF CFI");
180175
// In theory the debug_frame info should be valid at all call sites
181176
// ("asynchronous unwind info" as it is sometimes called) but in practice
182177
// gcc et al all emit call frame info for the prologue and call sites, but
183178
// not for the epilogue or all the other locations during the function
184179
// reliably.
185-
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
186-
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
187-
unwind_plan.SetRegisterKind(GetRegisterKind());
188-
189-
unwind_plan.SetPlanValidAddressRanges({fde->range});
190-
unwind_plan.SetUnwindPlanForSignalTrap(fde->for_signal_trap ? eLazyBoolYes
191-
: eLazyBoolNo);
192-
unwind_plan.SetReturnAddressRegister(fde->return_addr_reg_num);
193-
int64_t slide =
194-
fde->range.GetBaseAddress().GetFileAddress() - addr.GetFileAddress();
195-
for (UnwindPlan::Row &row : fde->rows) {
196-
row.SlideOffset(slide);
197-
unwind_plan.AppendRow(std::move(row));
180+
result->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
181+
result->SetSourcedFromCompiler(eLazyBoolYes);
182+
result->SetUnwindPlanForSignalTrap(eLazyBoolNo);
183+
for (const AddressRange &range : ranges) {
184+
std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range);
185+
if (!entry)
186+
continue;
187+
std::optional<FDE> fde = ParseFDE(entry->data, addr);
188+
if (!fde)
189+
continue;
190+
int64_t slide =
191+
fde->range.GetBaseAddress().GetFileAddress() - addr.GetFileAddress();
192+
valid_ranges.push_back(std::move(fde->range));
193+
if (fde->for_signal_trap)
194+
result->SetUnwindPlanForSignalTrap(eLazyBoolYes);
195+
result->SetReturnAddressRegister(fde->return_addr_reg_num);
196+
for (UnwindPlan::Row &row : fde->rows) {
197+
row.SlideOffset(slide);
198+
result->AppendRow(std::move(row));
199+
}
198200
}
199-
200-
return true;
201+
result->SetPlanValidAddressRanges(std::move(valid_ranges));
202+
if (result->GetRowCount() == 0)
203+
return nullptr;
204+
return result;
201205
}
202206

203207
bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {

lldb/source/Symbol/FuncUnwinders.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,9 @@ FuncUnwinders::GetEHFrameUnwindPlan(Target &target) {
149149
return m_unwind_plan_eh_frame_sp;
150150

151151
m_tried_unwind_plan_eh_frame = true;
152-
if (m_range.GetBaseAddress().IsValid()) {
153-
DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
154-
if (eh_frame) {
155-
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
156-
if (eh_frame->GetUnwindPlan(m_range, *plan_sp))
157-
m_unwind_plan_eh_frame_sp = std::move(plan_sp);
158-
}
152+
if (m_addr.IsValid()) {
153+
if (DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo())
154+
m_unwind_plan_eh_frame_sp = eh_frame->GetUnwindPlan(m_ranges, m_addr);
159155
}
160156
return m_unwind_plan_eh_frame_sp;
161157
}
@@ -167,13 +163,10 @@ FuncUnwinders::GetDebugFrameUnwindPlan(Target &target) {
167163
return m_unwind_plan_debug_frame_sp;
168164

169165
m_tried_unwind_plan_debug_frame = true;
170-
if (m_range.GetBaseAddress().IsValid()) {
171-
DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
172-
if (debug_frame) {
173-
auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
174-
if (debug_frame->GetUnwindPlan(m_range, *plan_sp))
175-
m_unwind_plan_debug_frame_sp = std::move(plan_sp);
176-
}
166+
if (!m_ranges.empty()) {
167+
if (DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo())
168+
m_unwind_plan_debug_frame_sp =
169+
debug_frame->GetUnwindPlan(m_ranges, m_addr);
177170
}
178171
return m_unwind_plan_debug_frame_sp;
179172
}

lldb/source/Symbol/UnwindTable.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ AddressRanges UnwindTable::GetAddressRanges(const Address &addr,
122122
return {};
123123
}
124124

125+
static Address GetFunctionOrSymbolAddress(const Address &addr,
126+
const SymbolContext &sc) {
127+
if (Address result = sc.GetFunctionOrSymbolAddress(); result.IsValid())
128+
return result;
129+
return addr;
130+
}
131+
125132
FuncUnwindersSP
126133
UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr,
127134
const SymbolContext &sc) {
@@ -131,25 +138,20 @@ UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr,
131138

132139
// There is an UnwindTable per object file, so we can safely use file handles
133140
addr_t file_addr = addr.GetFileAddress();
134-
iterator end = m_unwinds.end();
135-
iterator insert_pos = end;
136-
if (!m_unwinds.empty()) {
137-
insert_pos = m_unwinds.lower_bound(file_addr);
138-
iterator pos = insert_pos;
139-
if ((pos == m_unwinds.end()) ||
140-
(pos != m_unwinds.begin() &&
141-
pos->second->GetFunctionStartAddress() != addr))
142-
--pos;
143-
141+
iterator insert_pos = m_unwinds.upper_bound(file_addr);
142+
if (insert_pos != m_unwinds.begin()) {
143+
auto pos = std::prev(insert_pos);
144144
if (pos->second->ContainsAddress(addr))
145145
return pos->second;
146146
}
147147

148+
Address start_addr = GetFunctionOrSymbolAddress(addr, sc);
148149
AddressRanges ranges = GetAddressRanges(addr, sc);
149150
if (ranges.empty())
150151
return nullptr;
151152

152-
auto func_unwinder_sp = std::make_shared<FuncUnwinders>(*this, addr, ranges);
153+
auto func_unwinder_sp =
154+
std::make_shared<FuncUnwinders>(*this, start_addr, ranges);
153155
for (const AddressRange &range : ranges)
154156
m_unwinds.emplace_hint(insert_pos, range.GetBaseAddress().GetFileAddress(),
155157
func_unwinder_sp);
@@ -164,11 +166,12 @@ FuncUnwindersSP UnwindTable::GetUncachedFuncUnwindersContainingAddress(
164166
const Address &addr, const SymbolContext &sc) {
165167
Initialize();
166168

169+
Address start_addr = GetFunctionOrSymbolAddress(addr, sc);
167170
AddressRanges ranges = GetAddressRanges(addr, sc);
168171
if (ranges.empty())
169172
return nullptr;
170173

171-
return std::make_shared<FuncUnwinders>(*this, addr, std::move(ranges));
174+
return std::make_shared<FuncUnwinders>(*this, start_addr, std::move(ranges));
172175
}
173176

174177
void UnwindTable::Dump(Stream &s) {

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -868,13 +868,11 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() {
868868

869869
// Even with -fomit-frame-pointer, we can try eh_frame to get back on
870870
// track.
871-
DWARFCallFrameInfo *eh_frame =
872-
pc_module_sp->GetUnwindTable().GetEHFrameInfo();
873-
if (eh_frame) {
874-
auto unwind_plan_sp =
875-
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
876-
if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp))
877-
return unwind_plan_sp;
871+
if (DWARFCallFrameInfo *eh_frame =
872+
pc_module_sp->GetUnwindTable().GetEHFrameInfo()) {
873+
if (std::unique_ptr<UnwindPlan> plan_up =
874+
eh_frame->GetUnwindPlan(m_current_pc))
875+
return plan_up;
878876
}
879877

880878
ArmUnwindInfo *arm_exidx =
@@ -1345,9 +1343,9 @@ RegisterContextUnwind::SavedLocationForRegister(
13451343
// value instead of the Return Address register.
13461344
// If $pc is not available, fall back to the RA reg.
13471345
UnwindPlan::Row::AbstractRegisterLocation scratch;
1348-
if (m_frame_type == eTrapHandlerFrame &&
1349-
active_row->GetRegisterInfo
1350-
(pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
1346+
if (m_frame_type == eTrapHandlerFrame && active_row &&
1347+
active_row->GetRegisterInfo(
1348+
pc_regnum.GetAsKind(unwindplan_registerkind), scratch)) {
13511349
UnwindLogMsg("Providing pc register instead of rewriting to "
13521350
"RA reg because this is a trap handler and there is "
13531351
"a location for the saved pc register value.");
@@ -1377,7 +1375,7 @@ RegisterContextUnwind::SavedLocationForRegister(
13771375
}
13781376
}
13791377

1380-
if (regnum.IsValid() &&
1378+
if (regnum.IsValid() && active_row &&
13811379
active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
13821380
unwindplan_regloc)) {
13831381
have_unwindplan_regloc = true;

lldb/test/Shell/Unwind/Inputs/basic-block-sections-with-dwarf.s

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
# int bar() { return foo(0); }
55
# int foo(int flag) { return flag ? bar() : baz(); }
66
# int main() { return foo(1); }
7-
# The function bar has been placed "in the middle" of foo.
7+
# The function bar has been placed "in the middle" of foo. The functions are not
8+
# using the frame pointer register and the are deliberately adjusting the stack
9+
# pointer to test that we're using the correct unwind row.
810

911
.text
1012

@@ -20,35 +22,36 @@ baz:
2022
.type foo,@function
2123
foo:
2224
.cfi_startproc
23-
pushq %rbp
25+
pushq %rbx
2426
.cfi_def_cfa_offset 16
25-
.cfi_offset %rbp, -16
26-
movq %rsp, %rbp
27-
.cfi_def_cfa_register %rbp
28-
subq $16, %rsp
29-
movl %edi, -8(%rbp)
30-
cmpl $0, -8(%rbp)
27+
.cfi_offset %rbx, -16
28+
movl %edi, %ebx
29+
cmpl $0, %ebx
3130
je foo.__part.2
3231
jmp foo.__part.1
3332
.cfi_endproc
3433
.Lfoo_end:
3534
.size foo, .Lfoo_end-foo
3635

36+
# NB: Deliberately inserting padding to separate the two parts of the function
37+
# as we're currently only parsing a single FDE entry from a (coalesced) address
38+
# range.
39+
nop
40+
3741
foo.__part.1:
3842
.cfi_startproc
39-
.cfi_def_cfa %rbp, 16
40-
.cfi_offset %rbp, -16
43+
.cfi_def_cfa_offset 16
44+
.cfi_offset %rbx, -16
45+
subq $16, %rsp
46+
.cfi_def_cfa_offset 32
4147
callq bar
42-
movl %eax, -4(%rbp)
4348
jmp foo.__part.3
4449
.Lfoo.__part.1_end:
4550
.size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1
4651
.cfi_endproc
4752

4853
bar:
4954
.cfi_startproc
50-
# NB: Decrease the stack pointer to make the unwind info for this function
51-
# different from the surrounding foo function.
5255
subq $24, %rsp
5356
.cfi_def_cfa_offset 32
5457
xorl %edi, %edi
@@ -62,22 +65,26 @@ bar:
6265

6366
foo.__part.2:
6467
.cfi_startproc
65-
.cfi_def_cfa %rbp, 16
66-
.cfi_offset %rbp, -16
68+
.cfi_def_cfa_offset 16
69+
.cfi_offset %rbx, -16
70+
subq $16, %rsp
71+
.cfi_def_cfa_offset 32
6772
callq baz
68-
movl %eax, -4(%rbp)
6973
jmp foo.__part.3
7074
.Lfoo.__part.2_end:
7175
.size foo.__part.2, .Lfoo.__part.2_end-foo.__part.2
7276
.cfi_endproc
7377

78+
# NB: Deliberately inserting padding to separate the two parts of the function
79+
# as we're currently only parsing a single FDE entry from a (coalesced) address
80+
# range.
81+
nop
82+
7483
foo.__part.3:
7584
.cfi_startproc
76-
.cfi_def_cfa %rbp, 16
77-
.cfi_offset %rbp, -16
78-
movl -4(%rbp), %eax
79-
addq $16, %rsp
80-
popq %rbp
85+
.cfi_def_cfa_offset 32
86+
.cfi_offset %rbx, -16
87+
addq $24, %rsp
8188
.cfi_def_cfa %rsp, 8
8289
retq
8390
.Lfoo.__part.3_end:
@@ -186,9 +193,8 @@ main:
186193
.byte 86
187194
.asciz "foo" # DW_AT_name
188195
.byte 4 # Abbrev [4] DW_TAG_formal_parameter
189-
.byte 2 # DW_AT_location
190-
.byte 145
191-
.byte 120
196+
.byte 1 # DW_AT_location
197+
.byte 0x53 # DW_OP_reg3
192198
.asciz "flag" # DW_AT_name
193199
.long .Lint-.Lcu_begin0 # DW_AT_type
194200
.byte 0 # End Of Children Mark

lldb/test/Shell/Unwind/basic-block-sections-with-dwarf-static.test

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,32 @@
1717
image show-unwind --cached true -n foo
1818
# CHECK: UNWIND PLANS for {{.*}}`foo
1919
#
20-
# CHECK: Assembly language inspection UnwindPlan:
21-
# CHECK-NEXT: This UnwindPlan originally sourced from assembly insn profiling
22-
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: no.
23-
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: yes.
20+
# CHECK: eh_frame UnwindPlan:
21+
# CHECK-NEXT: This UnwindPlan originally sourced from eh_frame CFI
22+
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes.
23+
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no.
2424
# CHECK-NEXT: This UnwindPlan is for a trap handler function: no.
25-
# TODO: This address range isn't correct right now. We're just checking that
26-
# it's a different range from the one in the next query.
27-
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 6-0x0000000000000046)
25+
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 6-0x0000000000000010)[{{.*}}.text + 17-0x000000000000001c)[{{.*}}.text + 44-0x0000000000000037)[{{.*}}.text + 56-0x000000000000003d)
26+
# CHECK-NEXT: row[0]: 0: CFA=rsp +8 => rip=[CFA-8]
27+
# CHECK-NEXT: row[1]: 1: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
28+
# CHECK-NEXT: row[2]: 11: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
29+
# CHECK-NEXT: row[3]: 15: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8]
30+
# CHECK-NEXT: row[4]: 38: CFA=rsp+16 => rbx=[CFA-16] rip=[CFA-8]
31+
# CHECK-NEXT: row[5]: 42: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8]
32+
# CHECK-NEXT: row[6]: 50: CFA=rsp+32 => rbx=[CFA-16] rip=[CFA-8]
33+
# CHECK-NEXT: row[7]: 54: CFA=rsp +8 => rbx=[CFA-16] rip=[CFA-8]
34+
# CHECK-EMPTY:
2835

2936
image show-unwind --cached true -n bar
3037
# CHECK: UNWIND PLANS for {{.*}}`bar
3138

32-
# CHECK: Assembly language inspection UnwindPlan:
33-
# CHECK-NEXT: This UnwindPlan originally sourced from assembly insn profiling
34-
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: no.
35-
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: yes.
39+
# CHECK: eh_frame UnwindPlan:
40+
# CHECK-NEXT: This UnwindPlan originally sourced from eh_frame CFI
41+
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes.
42+
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no.
3643
# CHECK-NEXT: This UnwindPlan is for a trap handler function: no.
37-
# TODO: This address range isn't correct right now. We're just checking that
38-
# it's a different range from the one in the previous query.
39-
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 35-0x0000000000000033)
44+
# CHECK-NEXT: Address range of this UnwindPlan: [{{.*}}.text + 28-0x000000000000002c)
45+
# CHECK-NEXT: row[0]: 0: CFA=rsp +8 => rip=[CFA-8]
46+
# CHECK-NEXT: row[1]: 4: CFA=rsp+32 => rip=[CFA-8]
47+
# CHECK-NEXT: row[2]: 15: CFA=rsp +8 => rip=[CFA-8]
48+
# CHECK-EMPTY:

0 commit comments

Comments
 (0)