1 //===-- ThreadPlanStepOverBreakpoint.cpp ------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/lldb-private-log.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/RegisterContext.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 //----------------------------------------------------------------------
26 // ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc.
27 //----------------------------------------------------------------------
28 
ThreadPlanStepOverBreakpoint(Thread & thread)29 ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
30     ThreadPlan (ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap",
31                 thread,
32                 eVoteNo,
33                 eVoteNoOpinion),  // We need to report the run since this happens
34                             // first in the thread plan stack when stepping
35                             // over a breakpoint
36     m_breakpoint_addr (LLDB_INVALID_ADDRESS),
37     m_auto_continue(false),
38     m_reenabled_breakpoint_site (false)
39 
40 {
41     m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
42     m_breakpoint_site_id =  m_thread.GetProcess()->GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
43 }
44 
~ThreadPlanStepOverBreakpoint()45 ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
46 {
47 }
48 
49 void
GetDescription(Stream * s,lldb::DescriptionLevel level)50 ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
51 {
52     s->Printf("Single stepping past breakpoint site %" PRIu64 " at 0x%" PRIx64, m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
53 }
54 
55 bool
ValidatePlan(Stream * error)56 ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
57 {
58     return true;
59 }
60 
61 bool
DoPlanExplainsStop(Event * event_ptr)62 ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr)
63 {
64     StopInfoSP stop_info_sp = GetPrivateStopInfo ();
65     if (stop_info_sp)
66     {
67         StopReason reason = stop_info_sp->GetStopReason();
68         if (reason == eStopReasonTrace || reason == eStopReasonNone)
69             return true;
70         else
71             return false;
72     }
73     return false;
74 }
75 
76 bool
ShouldStop(Event * event_ptr)77 ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
78 {
79     return false;
80 }
81 
82 bool
StopOthers()83 ThreadPlanStepOverBreakpoint::StopOthers ()
84 {
85     return true;
86 }
87 
88 StateType
GetPlanRunState()89 ThreadPlanStepOverBreakpoint::GetPlanRunState ()
90 {
91     return eStateStepping;
92 }
93 
94 bool
DoWillResume(StateType resume_state,bool current_plan)95 ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
96 {
97     if (current_plan)
98     {
99         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
100         if (bp_site_sp  && bp_site_sp->IsEnabled())
101             m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
102     }
103     return true;
104 }
105 
106 bool
WillStop()107 ThreadPlanStepOverBreakpoint::WillStop ()
108 {
109     ReenableBreakpointSite ();
110     return true;
111 }
112 
113 bool
MischiefManaged()114 ThreadPlanStepOverBreakpoint::MischiefManaged ()
115 {
116     lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
117 
118     if (pc_addr == m_breakpoint_addr)
119     {
120         // If we are still at the PC of our breakpoint, then for some reason we didn't
121         // get a chance to run.
122         return false;
123     }
124     else
125     {
126         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
127         if (log)
128             log->Printf("Completed step over breakpoint plan.");
129         // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
130         ReenableBreakpointSite ();
131         ThreadPlan::MischiefManaged ();
132         return true;
133     }
134 }
135 
136 void
ReenableBreakpointSite()137 ThreadPlanStepOverBreakpoint::ReenableBreakpointSite ()
138 {
139     if (!m_reenabled_breakpoint_site)
140     {
141         m_reenabled_breakpoint_site = true;
142         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
143         if (bp_site_sp)
144         {
145             m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
146         }
147     }
148 }
149 void
ThreadDestroyed()150 ThreadPlanStepOverBreakpoint::ThreadDestroyed ()
151 {
152     ReenableBreakpointSite ();
153 }
154 
155 void
SetAutoContinue(bool do_it)156 ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
157 {
158     m_auto_continue = do_it;
159 }
160 
161 bool
ShouldAutoContinue(Event * event_ptr)162 ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
163 {
164     return m_auto_continue;
165 }
166