diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp | 61 | 
1 files changed, 47 insertions, 14 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp index f2db6e4b6f42..378de53fafd7 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/contrib/llvm/tools/lldb/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;      }    }  | 
