Skip to content

Commit b6388e4

Browse files
committed
Decr return pc mid-stack when picking UnwindPlan row
When picking the UnwindPlan row to use to backtrace, off of the zeroth frame, decrement the return pc so we're in the address range of the call instruction. If this is a noretrun function call, the instruction at the "return address" is likely an entirely different basic block with possibly very different unwind rules, and this can cause the backtrace to be incorrect. Differential Revision: https://reviews.llvm.org/D124957 rdar://84651805
1 parent 586802e commit b6388e4

File tree

2 files changed

+17
-17
lines changed

2 files changed

+17
-17
lines changed

lldb/include/lldb/Target/RegisterContextUnwind.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,7 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
203203
void UnwindLogMsgVerbose(const char *fmt, ...)
204204
__attribute__((format(printf, 2, 3)));
205205

206-
bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp,
207-
int &valid_pc_offset);
206+
bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp);
208207

209208
lldb::addr_t GetReturnAddressHint(int32_t plan_offset);
210209

lldb/source/Target/RegisterContextUnwind.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ RegisterContextUnwind::RegisterContextUnwind(Thread &thread,
8282
}
8383

8484
bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC(
85-
lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) {
85+
lldb::UnwindPlanSP unwind_plan_sp) {
8686
if (!unwind_plan_sp)
8787
return false;
8888

8989
// check if m_current_pc is valid
9090
if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
9191
// yes - current offset can be used as is
92-
valid_pc_offset = m_current_offset;
9392
return true;
9493
}
9594

@@ -101,8 +100,6 @@ bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC(
101100
Address pc_minus_one(m_current_pc);
102101
pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1);
103102
if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) {
104-
// *valid_pc_offset = m_current_offset - 1;
105-
valid_pc_offset = m_current_pc.GetOffset() - 1;
106103
return true;
107104
}
108105

@@ -514,9 +511,12 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
514511
} else if (!addr_range.GetBaseAddress().IsValid() ||
515512
addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() ||
516513
addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) {
517-
// If our "current" pc isn't the start of a function, no need
518-
// to decrement and recompute.
519-
decr_pc_and_recompute_addr_range = false;
514+
// If our "current" pc isn't the start of a function, decrement the pc
515+
// if we're up the stack.
516+
if (m_behaves_like_zeroth_frame)
517+
decr_pc_and_recompute_addr_range = false;
518+
else
519+
decr_pc_and_recompute_addr_range = true;
520520
} else if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
521521
// Signal dispatch may set the return address of the handler it calls to
522522
// point to the first byte of a return trampoline (like __kernel_rt_sigreturn),
@@ -636,9 +636,9 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
636636
}
637637
} else {
638638
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
639-
int valid_offset = -1;
640-
if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) {
641-
active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset);
639+
if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp)) {
640+
active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(
641+
m_current_offset_backed_up_one);
642642
row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
643643
PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
644644
if (active_row.get() && log) {
@@ -1007,8 +1007,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
10071007
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite(
10081008
process->GetTarget(), m_thread);
10091009
}
1010-
int valid_offset = -1;
1011-
if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) {
1010+
if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
10121011
UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this "
10131012
"is the call-site unwind plan",
10141013
unwind_plan_sp->GetSourceName().GetCString());
@@ -1047,7 +1046,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() {
10471046
}
10481047
}
10491048

1050-
if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) {
1049+
if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
10511050
UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we "
10521051
"failed to find a call-site unwind plan that would work",
10531052
unwind_plan_sp->GetSourceName().GetCString());
@@ -1313,7 +1312,8 @@ RegisterContextUnwind::SavedLocationForRegister(
13131312
LLDB_REGNUM_GENERIC_PC);
13141313

13151314
UnwindPlan::RowSP active_row =
1316-
m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
1315+
m_full_unwind_plan_sp->GetRowForFunctionOffset(
1316+
m_current_offset_backed_up_one);
13171317
unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind();
13181318

13191319
if (got_new_full_unwindplan && active_row.get() && log) {
@@ -1770,7 +1770,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
17701770
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
17711771

17721772
UnwindPlan::RowSP active_row =
1773-
m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
1773+
m_fallback_unwind_plan_sp->GetRowForFunctionOffset(
1774+
m_current_offset_backed_up_one);
17741775

17751776
if (active_row &&
17761777
active_row->GetCFAValue().GetValueType() !=

0 commit comments

Comments
 (0)