@@ -38,6 +38,32 @@ using namespace lldb_private;
38
38
39
39
uint32_t ThreadPlanStepOut::s_default_flag_values = 0 ;
40
40
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
+
41
67
// ThreadPlanStepOut: Step out of the current frame
42
68
ThreadPlanStepOut::ThreadPlanStepOut (
43
69
Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
@@ -54,33 +80,46 @@ ThreadPlanStepOut::ThreadPlanStepOut(
54
80
m_stop_others(stop_others), m_immediate_step_from_function(nullptr ),
55
81
m_is_swift_error_value(false ),
56
82
m_calculate_return_value(gather_return_value) {
57
- Log *log = GetLog (LLDBLog::Step);
58
83
SetFlagsToDefault ();
59
84
SetupAvoidNoDebug (step_out_avoids_code_without_debug_info);
60
85
61
86
m_step_from_insn = thread.GetRegisterContext ()->GetPC (0 );
62
87
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 );
65
90
StackFrameSP immediate_return_from_sp (thread.GetStackFrameAtIndex (frame_idx));
66
91
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
+ }
69
95
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 );
73
109
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);
76
113
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.
84
123
85
124
m_step_out_to_id = return_frame_sp->GetStackID ();
86
125
m_immediate_step_from_id = immediate_return_from_sp->GetStackID ();
@@ -94,8 +133,8 @@ ThreadPlanStepOut::ThreadPlanStepOut(
94
133
// First queue a plan that gets us to this inlined frame, and when we get
95
134
// there we'll queue a second plan that walks us out of this frame.
96
135
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);
99
138
static_cast <ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get ())
100
139
->SetShouldStopHereCallbacks (nullptr , nullptr );
101
140
m_step_out_to_inline_plan_sp->SetPrivate (true );
@@ -135,6 +174,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
135
174
136
175
// Perform some additional validation on the return address.
137
176
uint32_t permissions = 0 ;
177
+ Log *log = GetLog (LLDBLog::Step);
138
178
if (!m_process.GetLoadAddressPermissions (m_return_addr, permissions)) {
139
179
LLDB_LOGF (log , " ThreadPlanStepOut(%p): Return address (0x%" PRIx64
140
180
" ) permissions not found." , static_cast <void *>(this ),
0 commit comments