|
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::ComputeReturnToFrame(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 = |
| 83 | + ComputeReturnToFrame(thread, frame_idx, m_flags); |
55 | 84 | StackFrameSP immediate_return_from_sp(thread.GetStackFrameAtIndex(frame_idx));
|
56 | 85 |
|
57 | 86 | if (!return_frame_sp || !immediate_return_from_sp)
|
58 | 87 | return; // we can't do anything here. ValidatePlan() will return false.
|
59 | 88 |
|
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 | 89 | m_step_out_to_id = return_frame_sp->GetStackID();
|
76 | 90 | m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
|
77 | 91 |
|
@@ -125,6 +139,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
|
125 | 139 |
|
126 | 140 | // Perform some additional validation on the return address.
|
127 | 141 | uint32_t permissions = 0;
|
| 142 | + Log *log = GetLog(LLDBLog::Step); |
128 | 143 | if (!m_process.GetLoadAddressPermissions(m_return_addr, permissions)) {
|
129 | 144 | LLDB_LOGF(log, "ThreadPlanStepOut(%p): Return address (0x%" PRIx64
|
130 | 145 | ") permissions not found.", static_cast<void *>(this),
|
|
0 commit comments