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 
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 
39 {
40     m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
41     m_breakpoint_site_id =  m_thread.GetProcess().GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr);
42 }
43 
44 ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint ()
45 {
46 }
47 
48 void
49 ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
50 {
51     s->Printf("Single stepping past breakpoint site %d at 0x%llx", m_breakpoint_site_id, (uint64_t)m_breakpoint_addr);
52 }
53 
54 bool
55 ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
56 {
57     return true;
58 }
59 
60 bool
61 ThreadPlanStepOverBreakpoint::PlanExplainsStop ()
62 {
63     return true;
64 }
65 
66 bool
67 ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
68 {
69     return false;
70 }
71 
72 bool
73 ThreadPlanStepOverBreakpoint::StopOthers ()
74 {
75     return true;
76 }
77 
78 StateType
79 ThreadPlanStepOverBreakpoint::GetPlanRunState ()
80 {
81     return eStateStepping;
82 }
83 
84 bool
85 ThreadPlanStepOverBreakpoint::WillResume (StateType resume_state, bool current_plan)
86 {
87     ThreadPlan::WillResume (resume_state, current_plan);
88 
89     if (current_plan)
90     {
91         BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
92         if (bp_site_sp  && bp_site_sp->IsEnabled())
93             m_thread.GetProcess().DisableBreakpoint (bp_site_sp.get());
94     }
95     return true;
96 }
97 
98 bool
99 ThreadPlanStepOverBreakpoint::WillStop ()
100 {
101     BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
102     if (bp_site_sp)
103         m_thread.GetProcess().EnableBreakpoint (bp_site_sp.get());
104     return true;
105 }
106 
107 bool
108 ThreadPlanStepOverBreakpoint::MischiefManaged ()
109 {
110     lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
111 
112     if (pc_addr == m_breakpoint_addr)
113     {
114         // If we are still at the PC of our breakpoint, then for some reason we didn't
115         // get a chance to run.
116         return false;
117     }
118     else
119     {
120         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
121         if (log)
122             log->Printf("Completed step over breakpoint plan.");
123         // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
124         BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
125         if (bp_site_sp)
126             m_thread.GetProcess().EnableBreakpoint (bp_site_sp.get());
127         ThreadPlan::MischiefManaged ();
128         return true;
129     }
130 }
131 
132 void
133 ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
134 {
135     m_auto_continue = do_it;
136 }
137 
138 bool
139 ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
140 {
141     return m_auto_continue;
142 }
143