@@ -38,6 +38,32 @@ using namespace lldb_private;
3838
3939uint32_t ThreadPlanStepOut::s_default_flag_values = 0 ;
4040
41+ // / Computes the target frame this plan should step out to.
42+ static StackFrameSP
43+ ComputeTargetFrame (Thread &thread, uint32_t start_frame_idx,
44+ std::vector<StackFrameSP> &skipped_frames) {
45+ uint32_t frame_idx = start_frame_idx + 1 ;
46+ StackFrameSP return_frame_sp = thread.GetStackFrameAtIndex (frame_idx);
47+ if (!return_frame_sp)
48+ return nullptr ;
49+
50+ while (return_frame_sp->IsArtificial () || return_frame_sp->IsHidden ()) {
51+ skipped_frames.push_back (return_frame_sp);
52+
53+ frame_idx++;
54+ return_frame_sp = thread.GetStackFrameAtIndex (frame_idx);
55+
56+ // We never expect to see an artificial frame without a regular ancestor.
57+ // Defensively refuse to step out.
58+ if (!return_frame_sp) {
59+ LLDB_LOG (GetLog (LLDBLog::Step),
60+ " Can't step out of frame with artificial ancestors" );
61+ return nullptr ;
62+ }
63+ }
64+ return return_frame_sp;
65+ }
66+
4167// ThreadPlanStepOut: Step out of the current frame
4268ThreadPlanStepOut::ThreadPlanStepOut (
4369 Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
@@ -54,33 +80,46 @@ ThreadPlanStepOut::ThreadPlanStepOut(
5480 m_stop_others(stop_others), m_immediate_step_from_function(nullptr ),
5581 m_is_swift_error_value(false ),
5682 m_calculate_return_value(gather_return_value) {
57- Log *log = GetLog (LLDBLog::Step);
5883 SetFlagsToDefault ();
5984 SetupAvoidNoDebug (step_out_avoids_code_without_debug_info);
6085
6186 m_step_from_insn = thread.GetRegisterContext ()->GetPC (0 );
6287
63- uint32_t return_frame_index = frame_idx + 1 ;
64- StackFrameSP return_frame_sp (thread. GetStackFrameAtIndex (return_frame_index) );
88+ StackFrameSP return_frame_sp =
89+ ComputeTargetFrame (thread, frame_idx, m_stepped_past_frames );
6590 StackFrameSP immediate_return_from_sp (thread.GetStackFrameAtIndex (frame_idx));
6691
67- if (!return_frame_sp || !immediate_return_from_sp)
68- return ; // we can't do anything here. ValidatePlan() will return false.
92+ SetupReturnAddress (return_frame_sp, immediate_return_from_sp, frame_idx,
93+ continue_to_next_branch);
94+ }
6995
70- // While stepping out, behave as-if artificial frames are not present.
71- while (return_frame_sp->IsArtificial () || return_frame_sp->IsHidden ()) {
72- m_stepped_past_frames.push_back (return_frame_sp);
96+ ThreadPlanStepOut::ThreadPlanStepOut (Thread &thread, bool stop_others,
97+ Vote report_stop_vote,
98+ Vote report_run_vote, uint32_t frame_idx,
99+ bool continue_to_next_branch,
100+ bool gather_return_value)
101+ : ThreadPlan(ThreadPlan::eKindStepOut, " Step out" , thread, report_stop_vote,
102+ report_run_vote),
103+ ThreadPlanShouldStopHere(this ), m_return_bp_id(LLDB_INVALID_BREAK_ID),
104+ m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
105+ m_immediate_step_from_function(nullptr ),
106+ m_calculate_return_value(gather_return_value) {
107+ SetFlagsToDefault ();
108+ m_step_from_insn = thread.GetRegisterContext ()->GetPC (0 );
73109
74- ++return_frame_index;
75- return_frame_sp = thread.GetStackFrameAtIndex (return_frame_index);
110+ StackFrameSP return_frame_sp = thread.GetStackFrameAtIndex (frame_idx + 1 );
111+ StackFrameSP immediate_return_from_sp =
112+ thread.GetStackFrameAtIndex (frame_idx);
76113
77- // We never expect to see an artificial frame without a regular ancestor.
78- // If this happens, log the issue and defensively refuse to step out.
79- if (!return_frame_sp) {
80- LLDB_LOG (log, " Can't step out of frame with artificial ancestors" );
81- return ;
82- }
83- }
114+ SetupReturnAddress (return_frame_sp, immediate_return_from_sp, frame_idx,
115+ continue_to_next_branch);
116+ }
117+
118+ void ThreadPlanStepOut::SetupReturnAddress (
119+ StackFrameSP return_frame_sp, StackFrameSP immediate_return_from_sp,
120+ uint32_t frame_idx, bool continue_to_next_branch) {
121+ if (!return_frame_sp || !immediate_return_from_sp)
122+ return ; // we can't do anything here. ValidatePlan() will return false.
84123
85124 m_step_out_to_id = return_frame_sp->GetStackID ();
86125 m_immediate_step_from_id = immediate_return_from_sp->GetStackID ();
@@ -94,8 +133,8 @@ ThreadPlanStepOut::ThreadPlanStepOut(
94133 // First queue a plan that gets us to this inlined frame, and when we get
95134 // there we'll queue a second plan that walks us out of this frame.
96135 m_step_out_to_inline_plan_sp = std::make_shared<ThreadPlanStepOut>(
97- thread , nullptr , false , stop_others, eVoteNoOpinion , eVoteNoOpinion,
98- frame_idx - 1 , eLazyBoolNo, continue_to_next_branch);
136+ GetThread () , nullptr , false , m_stop_others , eVoteNoOpinion,
137+ eVoteNoOpinion, frame_idx - 1 , eLazyBoolNo, continue_to_next_branch);
99138 static_cast <ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get ())
100139 ->SetShouldStopHereCallbacks (nullptr , nullptr );
101140 m_step_out_to_inline_plan_sp->SetPrivate (true );
@@ -135,6 +174,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
135174
136175 // Perform some additional validation on the return address.
137176 uint32_t permissions = 0 ;
177+ Log *log = GetLog (LLDBLog::Step);
138178 if (!m_process.GetLoadAddressPermissions (m_return_addr, permissions)) {
139179 LLDB_LOGF (log, " ThreadPlanStepOut(%p): Return address (0x%" PRIx64
140180 " ) permissions not found." , static_cast <void *>(this ),
0 commit comments