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 %" PRIu64 " at 0x%" PRIx64, 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::DoPlanExplainsStop (Event *event_ptr)
62 {
63     StopInfoSP stop_info_sp = GetPrivateStopReason();
64     if (stop_info_sp)
65     {
66         StopReason reason = stop_info_sp->GetStopReason();
67         if (reason == eStopReasonTrace || reason == eStopReasonNone)
68             return true;
69         else
70             return false;
71     }
72     return false;
73 }
74 
75 bool
76 ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr)
77 {
78     return false;
79 }
80 
81 bool
82 ThreadPlanStepOverBreakpoint::StopOthers ()
83 {
84     return true;
85 }
86 
87 StateType
88 ThreadPlanStepOverBreakpoint::GetPlanRunState ()
89 {
90     return eStateStepping;
91 }
92 
93 bool
94 ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
95 {
96     if (current_plan)
97     {
98         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
99         if (bp_site_sp  && bp_site_sp->IsEnabled())
100             m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
101     }
102     return true;
103 }
104 
105 bool
106 ThreadPlanStepOverBreakpoint::WillStop ()
107 {
108     BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
109     if (bp_site_sp)
110         m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
111     return true;
112 }
113 
114 bool
115 ThreadPlanStepOverBreakpoint::MischiefManaged ()
116 {
117     lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
118 
119     if (pc_addr == m_breakpoint_addr)
120     {
121         // If we are still at the PC of our breakpoint, then for some reason we didn't
122         // get a chance to run.
123         return false;
124     }
125     else
126     {
127         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
128         if (log)
129             log->Printf("Completed step over breakpoint plan.");
130         // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
131         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
132         if (bp_site_sp)
133             m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
134         ThreadPlan::MischiefManaged ();
135         return true;
136     }
137 }
138 
139 void
140 ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
141 {
142     m_auto_continue = do_it;
143 }
144 
145 bool
146 ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
147 {
148     return m_auto_continue;
149 }
150