summaryrefslogtreecommitdiff
path: root/source/Target/ThreadPlanStepOverBreakpoint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/ThreadPlanStepOverBreakpoint.cpp')
-rw-r--r--source/Target/ThreadPlanStepOverBreakpoint.cpp93
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));