aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp87
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