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::PlanExplainsStop (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::WillResume (StateType resume_state, bool current_plan)
95 {
96     ThreadPlan::WillResume (resume_state, current_plan);
97 
98     if (current_plan)
99     {
100         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
101         if (bp_site_sp  && bp_site_sp->IsEnabled())
102             m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get());
103     }
104     return true;
105 }
106 
107 bool
108 ThreadPlanStepOverBreakpoint::WillStop ()
109 {
110     BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
111     if (bp_site_sp)
112         m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
113     return true;
114 }
115 
116 bool
117 ThreadPlanStepOverBreakpoint::MischiefManaged ()
118 {
119     lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC();
120 
121     if (pc_addr == m_breakpoint_addr)
122     {
123         // If we are still at the PC of our breakpoint, then for some reason we didn't
124         // get a chance to run.
125         return false;
126     }
127     else
128     {
129         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
130         if (log)
131             log->Printf("Completed step over breakpoint plan.");
132         // Otherwise, re-enable the breakpoint we were stepping over, and we're done.
133         BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
134         if (bp_site_sp)
135             m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
136         ThreadPlan::MischiefManaged ();
137         return true;
138     }
139 }
140 
141 void
142 ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
143 {
144     m_auto_continue = do_it;
145 }
146 
147 bool
148 ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr)
149 {
150     return m_auto_continue;
151 }
152