diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp')
| -rw-r--r-- | contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp | 87 |
1 files changed, 65 insertions, 22 deletions
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp index 0a1e2ae605ef..0628451a5abf 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp @@ -9,7 +9,6 @@ #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Value.h" -#include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -23,6 +22,7 @@ #include "lldb/Target/ThreadPlanStepThrough.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "lldb/ValueObject/ValueObjectConstResult.h" #include <memory> @@ -31,6 +31,32 @@ using namespace lldb_private; uint32_t ThreadPlanStepOut::s_default_flag_values = 0; +/// Computes the target frame this plan should step out to. +static StackFrameSP +ComputeTargetFrame(Thread &thread, uint32_t start_frame_idx, + std::vector<StackFrameSP> &skipped_frames) { + uint32_t frame_idx = start_frame_idx + 1; + StackFrameSP return_frame_sp = thread.GetStackFrameAtIndex(frame_idx); + if (!return_frame_sp) + return nullptr; + + while (return_frame_sp->IsArtificial() || return_frame_sp->IsHidden()) { + skipped_frames.push_back(return_frame_sp); + + frame_idx++; + return_frame_sp = thread.GetStackFrameAtIndex(frame_idx); + + // We never expect to see an artificial frame without a regular ancestor. + // Defensively refuse to step out. + if (!return_frame_sp) { + LLDB_LOG(GetLog(LLDBLog::Step), + "Can't step out of frame with artificial ancestors"); + return nullptr; + } + } + return return_frame_sp; +} + // ThreadPlanStepOut: Step out of the current frame ThreadPlanStepOut::ThreadPlanStepOut( Thread &thread, SymbolContext *context, bool first_insn, bool stop_others, @@ -44,33 +70,46 @@ ThreadPlanStepOut::ThreadPlanStepOut( m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others), m_immediate_step_from_function(nullptr), m_calculate_return_value(gather_return_value) { - Log *log = GetLog(LLDBLog::Step); SetFlagsToDefault(); SetupAvoidNoDebug(step_out_avoids_code_without_debug_info); m_step_from_insn = thread.GetRegisterContext()->GetPC(0); - uint32_t return_frame_index = frame_idx + 1; - StackFrameSP return_frame_sp(thread.GetStackFrameAtIndex(return_frame_index)); + StackFrameSP return_frame_sp = + ComputeTargetFrame(thread, frame_idx, m_stepped_past_frames); StackFrameSP immediate_return_from_sp(thread.GetStackFrameAtIndex(frame_idx)); - if (!return_frame_sp || !immediate_return_from_sp) - return; // we can't do anything here. ValidatePlan() will return false. + SetupReturnAddress(return_frame_sp, immediate_return_from_sp, frame_idx, + continue_to_next_branch); +} - // While stepping out, behave as-if artificial frames are not present. - while (return_frame_sp->IsArtificial()) { - m_stepped_past_frames.push_back(return_frame_sp); +ThreadPlanStepOut::ThreadPlanStepOut(Thread &thread, bool stop_others, + Vote report_stop_vote, + Vote report_run_vote, uint32_t frame_idx, + bool continue_to_next_branch, + bool gather_return_value) + : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, report_stop_vote, + report_run_vote), + ThreadPlanShouldStopHere(this), m_return_bp_id(LLDB_INVALID_BREAK_ID), + m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others), + m_immediate_step_from_function(nullptr), + m_calculate_return_value(gather_return_value) { + SetFlagsToDefault(); + m_step_from_insn = thread.GetRegisterContext()->GetPC(0); - ++return_frame_index; - return_frame_sp = thread.GetStackFrameAtIndex(return_frame_index); + StackFrameSP return_frame_sp = thread.GetStackFrameAtIndex(frame_idx + 1); + StackFrameSP immediate_return_from_sp = + thread.GetStackFrameAtIndex(frame_idx); - // We never expect to see an artificial frame without a regular ancestor. - // If this happens, log the issue and defensively refuse to step out. - if (!return_frame_sp) { - LLDB_LOG(log, "Can't step out of frame with artificial ancestors"); - return; - } - } + SetupReturnAddress(return_frame_sp, immediate_return_from_sp, frame_idx, + continue_to_next_branch); +} + +void ThreadPlanStepOut::SetupReturnAddress( + StackFrameSP return_frame_sp, StackFrameSP immediate_return_from_sp, + uint32_t frame_idx, bool continue_to_next_branch) { + if (!return_frame_sp || !immediate_return_from_sp) + return; // we can't do anything here. ValidatePlan() will return false. m_step_out_to_id = return_frame_sp->GetStackID(); m_immediate_step_from_id = immediate_return_from_sp->GetStackID(); @@ -84,8 +123,8 @@ ThreadPlanStepOut::ThreadPlanStepOut( // First queue a plan that gets us to this inlined frame, and when we get // there we'll queue a second plan that walks us out of this frame. m_step_out_to_inline_plan_sp = std::make_shared<ThreadPlanStepOut>( - thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion, - frame_idx - 1, eLazyBoolNo, continue_to_next_branch); + GetThread(), nullptr, false, m_stop_others, eVoteNoOpinion, + eVoteNoOpinion, frame_idx - 1, eLazyBoolNo, continue_to_next_branch); static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get()) ->SetShouldStopHereCallbacks(nullptr, nullptr); m_step_out_to_inline_plan_sp->SetPrivate(true); @@ -125,6 +164,7 @@ ThreadPlanStepOut::ThreadPlanStepOut( // Perform some additional validation on the return address. uint32_t permissions = 0; + Log *log = GetLog(LLDBLog::Step); if (!m_process.GetLoadAddressPermissions(m_return_addr, permissions)) { LLDB_LOGF(log, "ThreadPlanStepOut(%p): Return address (0x%" PRIx64 ") permissions not found.", static_cast<void *>(this), @@ -364,8 +404,11 @@ bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) { } if (!done) { - StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID(); - done = !(frame_zero_id < m_step_out_to_id); + StopInfoSP stop_info_sp = GetPrivateStopInfo(); + if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { + StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID(); + done = !(frame_zero_id < m_step_out_to_id); + } } // The normal step out computations think we are done, so all we need to do |
