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