summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
new file mode 100644
index 0000000..6f285e2
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -0,0 +1,194 @@
+//===-- ThreadPlanStepOverBreakpoint.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc.
+//----------------------------------------------------------------------
+
+ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
+ ThreadPlan (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
+ m_breakpoint_addr (LLDB_INVALID_ADDRESS),
+ m_auto_continue(false),
+ m_reenabled_breakpoint_site (false)
+
+{
+ m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
+ m_breakpoint_site_id = m_thread.GetProcess()->GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
+}
+
+ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
+{
+}
+
+void
+ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+ s->Printf("Single stepping past breakpoint site %" PRIu64 " at 0x%" PRIx64, m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
+}
+
+bool
+ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
+{
+ return true;
+}
+
+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
+ // 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.
+ StopReason reason = stop_info_sp->GetStopReason();
+
+ 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;
+ }
+ }
+ return false;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
+{
+ return !ShouldAutoContinue(event_ptr);
+}
+
+bool
+ThreadPlanStepOverBreakpoint::StopOthers ()
+{
+ return true;
+}
+
+StateType
+ThreadPlanStepOverBreakpoint::GetPlanRunState ()
+{
+ return eStateStepping;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
+{
+ if (current_plan)
+ {
+ BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
+ if (bp_site_sp && bp_site_sp->IsEnabled())
+ m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
+ }
+ return true;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::WillStop ()
+{
+ ReenableBreakpointSite ();
+ return true;
+}
+
+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.
+ return false;
+ }
+ else
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf("Completed step over breakpoint plan.");
+ // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
+ ReenableBreakpointSite ();
+ ThreadPlan::MischiefManaged ();
+ return true;
+ }
+}
+
+void
+ThreadPlanStepOverBreakpoint::ReenableBreakpointSite ()
+{
+ if (!m_reenabled_breakpoint_site)
+ {
+ m_reenabled_breakpoint_site = true;
+ BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
+ if (bp_site_sp)
+ {
+ m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
+ }
+ }
+}
+void
+ThreadPlanStepOverBreakpoint::ThreadDestroyed ()
+{
+ ReenableBreakpointSite ();
+}
+
+void
+ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
+{
+ m_auto_continue = do_it;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
+{
+ return m_auto_continue;
+}
+
+bool
+ThreadPlanStepOverBreakpoint::IsPlanStale()
+{
+ return m_thread.GetRegisterContext()->GetPC() != m_breakpoint_addr;
+}
+
OpenPOWER on IntegriCloud