Author: Jason Molenda Date: 2022-05-05T14:18:21-07:00 New Revision: b6388e4a0050fa248f774f5dacfa3e566e8daef1
URL: https://github.com/llvm/llvm-project/commit/b6388e4a0050fa248f774f5dacfa3e566e8daef1 DIFF: https://github.com/llvm/llvm-project/commit/b6388e4a0050fa248f774f5dacfa3e566e8daef1.diff LOG: 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 Added: Modified: lldb/include/lldb/Target/RegisterContextUnwind.h lldb/source/Target/RegisterContextUnwind.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Target/RegisterContextUnwind.h b/lldb/include/lldb/Target/RegisterContextUnwind.h index ef03a6746d723..ef8ae88403866 100644 --- a/lldb/include/lldb/Target/RegisterContextUnwind.h +++ b/lldb/include/lldb/Target/RegisterContextUnwind.h @@ -203,8 +203,7 @@ class RegisterContextUnwind : public lldb_private::RegisterContext { void UnwindLogMsgVerbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, - int &valid_pc_offset); + bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp); lldb::addr_t GetReturnAddressHint(int32_t plan_offset); diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index 339e4c6ad0fde..e98aed7e15552 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -82,14 +82,13 @@ RegisterContextUnwind::RegisterContextUnwind(Thread &thread, } bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC( - lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) { + lldb::UnwindPlanSP unwind_plan_sp) { if (!unwind_plan_sp) return false; // check if m_current_pc is valid if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { // yes - current offset can be used as is - valid_pc_offset = m_current_offset; return true; } @@ -101,8 +100,6 @@ bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC( Address pc_minus_one(m_current_pc); pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) { - // *valid_pc_offset = m_current_offset - 1; - valid_pc_offset = m_current_pc.GetOffset() - 1; return true; } @@ -514,9 +511,12 @@ void RegisterContextUnwind::InitializeNonZerothFrame() { } else if (!addr_range.GetBaseAddress().IsValid() || addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { - // If our "current" pc isn't the start of a function, no need - // to decrement and recompute. - decr_pc_and_recompute_addr_range = false; + // If our "current" pc isn't the start of a function, decrement the pc + // if we're up the stack. + if (m_behaves_like_zeroth_frame) + decr_pc_and_recompute_addr_range = false; + else + decr_pc_and_recompute_addr_range = true; } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { // Signal dispatch may set the return address of the handler it calls to // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), @@ -636,9 +636,9 @@ void RegisterContextUnwind::InitializeNonZerothFrame() { } } else { m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); - int valid_offset = -1; - if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { - active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset); + if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp)) { + active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset( + m_current_offset_backed_up_one); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); if (active_row.get() && log) { @@ -1007,8 +1007,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() { unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( process->GetTarget(), m_thread); } - int valid_offset = -1; - if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) { UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " "is the call-site unwind plan", unwind_plan_sp->GetSourceName().GetCString()); @@ -1047,7 +1046,7 @@ UnwindPlanSP RegisterContextUnwind::GetFullUnwindPlanForFrame() { } } - if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) { UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we " "failed to find a call-site unwind plan that would work", unwind_plan_sp->GetSourceName().GetCString()); @@ -1313,7 +1312,8 @@ RegisterContextUnwind::SavedLocationForRegister( LLDB_REGNUM_GENERIC_PC); UnwindPlan::RowSP active_row = - m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + m_full_unwind_plan_sp->GetRowForFunctionOffset( + m_current_offset_backed_up_one); unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); if (got_new_full_unwindplan && active_row.get() && log) { @@ -1770,7 +1770,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() { m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; UnwindPlan::RowSP active_row = - m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + m_fallback_unwind_plan_sp->GetRowForFunctionOffset( + m_current_offset_backed_up_one); if (active_row && active_row->GetCFAValue().GetValueType() != _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits