diff options
Diffstat (limited to 'source/Target/ThreadPlanStepOut.cpp')
-rw-r--r-- | source/Target/ThreadPlanStepOut.cpp | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp index f2db6e4b6f42..378de53fafd7 100644 --- a/source/Target/ThreadPlanStepOut.cpp +++ b/source/Target/ThreadPlanStepOut.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Value.h" @@ -48,18 +44,36 @@ 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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); SetFlagsToDefault(); SetupAvoidNoDebug(step_out_avoids_code_without_debug_info); m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0); - StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1)); + uint32_t return_frame_index = frame_idx + 1; + StackFrameSP return_frame_sp( + m_thread.GetStackFrameAtIndex(return_frame_index)); StackFrameSP immediate_return_from_sp( m_thread.GetStackFrameAtIndex(frame_idx)); if (!return_frame_sp || !immediate_return_from_sp) return; // we can't do anything here. ValidatePlan() will return false. + // 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); + + ++return_frame_index; + return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index); + + // 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; + } + } + m_step_out_to_id = return_frame_sp->GetStackID(); m_immediate_step_from_id = immediate_return_from_sp->GetStackID(); @@ -67,7 +81,7 @@ ThreadPlanStepOut::ThreadPlanStepOut( // have to be a little more careful. It is non-trivial to determine the real // "return code address" for an inlined frame, so we have to work our way to // that frame and then step out. - if (immediate_return_from_sp && immediate_return_from_sp->IsInlined()) { + if (immediate_return_from_sp->IsInlined()) { if (frame_idx > 0) { // 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. @@ -82,7 +96,7 @@ ThreadPlanStepOut::ThreadPlanStepOut( // just do that now. QueueInlinedStepPlan(false); } - } else if (return_frame_sp) { + } else { // Find the return address and set a breakpoint there: // FIXME - can we do this more securely if we know first_insn? @@ -115,7 +129,10 @@ ThreadPlanStepOut::ThreadPlanStepOut( Breakpoint *return_bp = m_thread.CalculateTarget() ->CreateBreakpoint(m_return_addr, true, false) .get(); + if (return_bp != nullptr) { + if (return_bp->IsHardware() && !return_bp->HasResolvedLocations()) + m_could_not_resolve_hw_bp = true; return_bp->SetThreadID(m_thread.GetID()); m_return_bp_id = return_bp->GetID(); return_bp->SetBreakpointKind("step-out"); @@ -198,19 +215,35 @@ void ThreadPlanStepOut::GetDescription(Stream *s, s->Printf(" using breakpoint site %d", m_return_bp_id); } } + + s->Printf("\n"); + for (StackFrameSP frame_sp : m_stepped_past_frames) { + s->Printf("Stepped out past: "); + frame_sp->DumpUsingSettingsFormat(s); + } } bool ThreadPlanStepOut::ValidatePlan(Stream *error) { if (m_step_out_to_inline_plan_sp) return m_step_out_to_inline_plan_sp->ValidatePlan(error); - else if (m_step_through_inline_plan_sp) + + if (m_step_through_inline_plan_sp) return m_step_through_inline_plan_sp->ValidatePlan(error); - else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) { + + if (m_could_not_resolve_hw_bp) { + if (error) + error->PutCString( + "Could not create hardware breakpoint for thread plan."); + return false; + } + + if (m_return_bp_id == LLDB_INVALID_BREAK_ID) { if (error) error->PutCString("Could not create return address breakpoint."); return false; - } else - return true; + } + + return true; } bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) { @@ -257,7 +290,7 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) { } if (done) { - if (InvokeShouldStopHereCallback(eFrameCompareOlder)) { + if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) { CalculateReturnValue(); SetPlanComplete(); } @@ -319,12 +352,12 @@ bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) { // is consult the ShouldStopHere, and we are done. if (done) { - if (InvokeShouldStopHereCallback(eFrameCompareOlder)) { + if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) { CalculateReturnValue(); SetPlanComplete(); } else { m_step_out_further_plan_sp = - QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder); + QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status); done = false; } } |