diff options
Diffstat (limited to 'source/Target/ThreadPlanStepOverBreakpoint.cpp')
| -rw-r--r-- | source/Target/ThreadPlanStepOverBreakpoint.cpp | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp index 3896a0b247145..7497dbff1729b 100644 --- a/source/Target/ThreadPlanStepOverBreakpoint.cpp +++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp @@ -31,8 +31,8 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint(Thread &thread) ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap", thread, eVoteNo, eVoteNoOpinion), // We need to report the run since this happens - // first in the thread plan stack when stepping - // over a breakpoint + // first in the thread plan stack when stepping over + // a breakpoint m_breakpoint_addr(LLDB_INVALID_ADDRESS), m_auto_continue(false), m_reenabled_breakpoint_site(false) @@ -57,42 +57,58 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) { StopInfoSP stop_info_sp = GetPrivateStopInfo(); if (stop_info_sp) { // It's a little surprising that we stop here for a breakpoint hit. - // However, when you single step ONTO a breakpoint - // we still want to call that a breakpoint hit, and trigger the actions, - // etc. Otherwise you would see the + // However, when you single step ONTO a breakpoint we still want to call + // that a breakpoint hit, and trigger the actions, etc. Otherwise you + // would see the // PC at the breakpoint without having triggered the actions, then you'd // continue, the PC wouldn't change, - // and you'd see the breakpoint hit, which would be odd. - // So the lower levels fake "step onto breakpoint address" and return that - // as a breakpoint. So our trace - // step COULD appear as a breakpoint hit if the next instruction also - // contained a breakpoint. + // and you'd see the breakpoint hit, which would be odd. So the lower + // levels fake "step onto breakpoint address" and return that as a + // breakpoint. So our trace step COULD appear as a breakpoint hit if the + // next instruction also contained a breakpoint. StopReason reason = stop_info_sp->GetStopReason(); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("Step over breakpoint stopped for reason: %s.", + Thread::StopReasonAsCString(reason)); + switch (reason) { - case eStopReasonTrace: - case eStopReasonNone: - return true; - case eStopReasonBreakpoint: - // It's a little surprising that we stop here for a breakpoint hit. - // However, when you single step ONTO a - // breakpoint we still want to call that a breakpoint hit, and trigger the - // actions, etc. Otherwise you - // would see the PC at the breakpoint without having triggered the - // actions, then you'd continue, the PC - // wouldn't change, and you'd see the breakpoint hit, which would be odd. - // So the lower levels fake "step onto breakpoint address" and return that - // as a breakpoint hit. So our trace - // step COULD appear as a breakpoint hit if the next instruction also - // contained a breakpoint. We don't want - // to handle that, since we really don't know what to do with breakpoint - // hits. But make sure we don't set - // ourselves to auto-continue or we'll wrench control away from the plans - // that can deal with this. - SetAutoContinue(false); - return false; - default: - return false; + case eStopReasonTrace: + case eStopReasonNone: + return true; + case eStopReasonBreakpoint: + { + // It's a little surprising that we stop here for a breakpoint hit. + // However, when you single step ONTO a breakpoint we still want to call + // that a breakpoint hit, and trigger the actions, etc. Otherwise you + // would see the PC at the breakpoint without having triggered the + // actions, then you'd continue, the PC wouldn't change, and you'd see + // the breakpoint hit, which would be odd. So the lower levels fake + // "step onto breakpoint address" and return that as a breakpoint hit. + // So our trace step COULD appear as a breakpoint hit if the next + // instruction also contained a breakpoint. We don't want to handle + // that, since we really don't know what to do with breakpoint hits. + // But make sure we don't set ourselves to auto-continue or we'll wrench + // control away from the plans that can deal with this. + // Be careful, however, as we may have "seen a breakpoint under the PC + // because we stopped without changing the PC, in which case we do want + // to re-claim this stop so we'll try again. + lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); + + if (pc_addr == m_breakpoint_addr) { + if (log) + log->Printf("Got breakpoint stop reason but pc: 0x%" PRIx64 + "hasn't changed.", pc_addr); + return true; + } + + SetAutoContinue(false); + return false; + } + default: + return false; } } return false; @@ -114,8 +130,10 @@ bool ThreadPlanStepOverBreakpoint::DoWillResume(StateType resume_state, BreakpointSiteSP bp_site_sp( m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress( m_breakpoint_addr)); - if (bp_site_sp && bp_site_sp->IsEnabled()) + if (bp_site_sp && bp_site_sp->IsEnabled()) { m_thread.GetProcess()->DisableBreakpointSite(bp_site_sp.get()); + m_reenabled_breakpoint_site = false; + } } return true; } @@ -125,13 +143,16 @@ bool ThreadPlanStepOverBreakpoint::WillStop() { return true; } +void ThreadPlanStepOverBreakpoint::WillPop() { + ReenableBreakpointSite(); +} + bool ThreadPlanStepOverBreakpoint::MischiefManaged() { lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); if (pc_addr == m_breakpoint_addr) { // If we are still at the PC of our breakpoint, then for some reason we - // didn't - // get a chance to run. + // didn't get a chance to run. return false; } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); |
