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