|
29 | 29 | using namespace lldb; |
30 | 30 | using namespace lldb_private; |
31 | 31 |
|
32 | | -uint32_t ThreadPlanStepOut::s_default_flag_values = 0; |
| 32 | +uint32_t ThreadPlanStepOut::s_default_flag_values = |
| 33 | + eStepOutPastArtificialFunctions | eStepOutPastHiddenFunctions; |
| 34 | + |
| 35 | +StackFrameSP ThreadPlanStepOut::ComputeTargetFrame(Thread &thread, |
| 36 | + uint32_t start_frame_idx, |
| 37 | + Flags flags) { |
| 38 | + uint32_t frame_idx = start_frame_idx + 1; |
| 39 | + StackFrameSP return_frame_sp = thread.GetStackFrameAtIndex(frame_idx); |
| 40 | + if (!return_frame_sp) |
| 41 | + return nullptr; |
| 42 | + |
| 43 | + // If asked to, step out past artificial/hidden frames. |
| 44 | + while ((flags.Test(eStepOutPastArtificialFunctions) && |
| 45 | + return_frame_sp->IsArtificial()) || |
| 46 | + (flags.Test(eStepOutPastHiddenFunctions) && |
| 47 | + return_frame_sp->IsHidden())) { |
| 48 | + m_stepped_past_frames.push_back(return_frame_sp); |
| 49 | + |
| 50 | + frame_idx++; |
| 51 | + return_frame_sp = thread.GetStackFrameAtIndex(frame_idx); |
| 52 | + |
| 53 | + // We never expect to see an artificial frame without a regular ancestor. |
| 54 | + // Defensively refuse to step out. |
| 55 | + if (!return_frame_sp) { |
| 56 | + LLDB_LOG(GetLog(LLDBLog::Step), |
| 57 | + "Can't step out of frame with artificial ancestors"); |
| 58 | + return nullptr; |
| 59 | + } |
| 60 | + } |
| 61 | + return return_frame_sp; |
| 62 | +} |
33 | 63 |
|
34 | 64 | // ThreadPlanStepOut: Step out of the current frame |
35 | 65 | ThreadPlanStepOut::ThreadPlanStepOut( |
36 | 66 | Thread &thread, SymbolContext *context, bool first_insn, bool stop_others, |
37 | 67 | Vote report_stop_vote, Vote report_run_vote, uint32_t frame_idx, |
38 | 68 | LazyBool step_out_avoids_code_without_debug_info, |
39 | | - bool continue_to_next_branch, bool gather_return_value) |
| 69 | + bool continue_to_next_branch, bool gather_return_value, Flags flags) |
40 | 70 | : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, report_stop_vote, |
41 | 71 | report_run_vote), |
42 | 72 | ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS), |
43 | 73 | m_return_bp_id(LLDB_INVALID_BREAK_ID), |
44 | 74 | m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others), |
45 | 75 | m_immediate_step_from_function(nullptr), |
46 | 76 | m_calculate_return_value(gather_return_value) { |
47 | | - Log *log = GetLog(LLDBLog::Step); |
48 | | - SetFlagsToDefault(); |
| 77 | + m_flags = flags; |
49 | 78 | SetupAvoidNoDebug(step_out_avoids_code_without_debug_info); |
50 | 79 |
|
51 | 80 | m_step_from_insn = thread.GetRegisterContext()->GetPC(0); |
52 | 81 |
|
53 | | - uint32_t return_frame_index = frame_idx + 1; |
54 | | - StackFrameSP return_frame_sp(thread.GetStackFrameAtIndex(return_frame_index)); |
| 82 | + StackFrameSP return_frame_sp = ComputeTargetFrame(thread, frame_idx, m_flags); |
55 | 83 | StackFrameSP immediate_return_from_sp(thread.GetStackFrameAtIndex(frame_idx)); |
56 | 84 |
|
57 | 85 | if (!return_frame_sp || !immediate_return_from_sp) |
58 | 86 | return; // we can't do anything here. ValidatePlan() will return false. |
59 | 87 |
|
60 | | - // While stepping out, behave as-if artificial frames are not present. |
61 | | - while (return_frame_sp->IsArtificial() || return_frame_sp->IsHidden()) { |
62 | | - m_stepped_past_frames.push_back(return_frame_sp); |
63 | | - |
64 | | - ++return_frame_index; |
65 | | - return_frame_sp = thread.GetStackFrameAtIndex(return_frame_index); |
66 | | - |
67 | | - // We never expect to see an artificial frame without a regular ancestor. |
68 | | - // If this happens, log the issue and defensively refuse to step out. |
69 | | - if (!return_frame_sp) { |
70 | | - LLDB_LOG(log, "Can't step out of frame with artificial ancestors"); |
71 | | - return; |
72 | | - } |
73 | | - } |
74 | | - |
75 | 88 | m_step_out_to_id = return_frame_sp->GetStackID(); |
76 | 89 | m_immediate_step_from_id = immediate_return_from_sp->GetStackID(); |
77 | 90 |
|
@@ -125,6 +138,7 @@ ThreadPlanStepOut::ThreadPlanStepOut( |
125 | 138 |
|
126 | 139 | // Perform some additional validation on the return address. |
127 | 140 | uint32_t permissions = 0; |
| 141 | + Log *log = GetLog(LLDBLog::Step); |
128 | 142 | if (!m_process.GetLoadAddressPermissions(m_return_addr, permissions)) { |
129 | 143 | LLDB_LOGF(log, "ThreadPlanStepOut(%p): Return address (0x%" PRIx64 |
130 | 144 | ") permissions not found.", static_cast<void *>(this), |
|
0 commit comments