1 //===-- ThreadPlanRunToAddress.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/ThreadPlanRunToAddress.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/Target.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Target/RegisterContext.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // ThreadPlanRunToAddress: Continue plan
29 //----------------------------------------------------------------------
30 
31 ThreadPlanRunToAddress::ThreadPlanRunToAddress
32 (
33     Thread &thread,
34     Address &address,
35     bool stop_others
36 ) :
37     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to breakpoint plan", thread, eVoteNoOpinion, eVoteNoOpinion),
38     m_stop_others (stop_others),
39     m_address (LLDB_INVALID_ADDRESS),
40     m_break_id (LLDB_INVALID_BREAK_ID)
41 {
42     m_address = address.GetLoadAddress(&m_thread.GetProcess());
43     SetInitialBreakpoint();
44 }
45 
46 ThreadPlanRunToAddress::ThreadPlanRunToAddress
47 (
48     Thread &thread,
49     lldb::addr_t address,
50     bool stop_others
51 ) :
52     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to breakpoint plan", thread, eVoteNoOpinion, eVoteNoOpinion),
53     m_stop_others (stop_others),
54     m_address (address),
55     m_break_id (LLDB_INVALID_BREAK_ID)
56 {
57     SetInitialBreakpoint();
58 }
59 
60 void
61 ThreadPlanRunToAddress::SetInitialBreakpoint ()
62 {
63     Breakpoint *breakpoint;
64     breakpoint = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_address, true).get();
65     if (breakpoint != NULL)
66     {
67         m_break_id = breakpoint->GetID();
68         breakpoint->SetThreadID(m_thread.GetID());
69     }
70 }
71 
72 ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
73 {
74     if (m_break_id != LLDB_INVALID_BREAK_ID)
75     {
76         m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_id);
77     }
78 }
79 
80 void
81 ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
82 {
83     if (level == lldb::eDescriptionLevelBrief)
84     {
85         s->Printf ("run to address: ");
86         s->Address (m_address, sizeof (addr_t));
87     }
88     else
89     {
90         s->Printf ("Run to address: ");
91         s->Address(m_address, sizeof (addr_t));
92         s->Printf (" using breakpoint: %d - ", m_break_id);
93         Breakpoint *breakpoint = m_thread.GetProcess().GetTarget().GetBreakpointByID (m_break_id).get();
94         if (breakpoint)
95             breakpoint->Dump (s);
96         else
97             s->Printf ("but the breakpoint has been deleted.");
98     }
99 }
100 
101 bool
102 ThreadPlanRunToAddress::ValidatePlan (Stream *error)
103 {
104     // If we couldn't set the breakpoint for some reason, then this won't
105     // work.
106     if(m_break_id == LLDB_INVALID_BREAK_ID)
107         return false;
108     else
109         return true;
110 }
111 
112 bool
113 ThreadPlanRunToAddress::PlanExplainsStop ()
114 {
115     return AtOurAddress();
116 }
117 
118 bool
119 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
120 {
121     return false;
122 }
123 
124 bool
125 ThreadPlanRunToAddress::StopOthers ()
126 {
127     return m_stop_others;
128 }
129 
130 void
131 ThreadPlanRunToAddress::SetStopOthers (bool new_value)
132 {
133     m_stop_others = new_value;
134 }
135 
136 StateType
137 ThreadPlanRunToAddress::RunState ()
138 {
139     return eStateRunning;
140 }
141 
142 bool
143 ThreadPlanRunToAddress::WillStop ()
144 {
145     return true;
146 }
147 
148 bool
149 ThreadPlanRunToAddress::MischiefManaged ()
150 {
151     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
152 
153     if (AtOurAddress())
154     {
155         // Remove the breakpoint
156         if (m_break_id != LLDB_INVALID_BREAK_ID)
157         {
158             m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_id);
159             m_break_id = LLDB_INVALID_BREAK_ID;
160         }
161 
162         if (log)
163             log->Printf("Completed run to address plan.");
164         ThreadPlan::MischiefManaged ();
165         return true;
166     }
167     else
168         return false;
169 }
170 
171 bool
172 ThreadPlanRunToAddress::AtOurAddress ()
173 {
174     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
175     return m_address == current_address;
176 }
177