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/Core/Log.h"
17 #include "lldb/Core/Stream.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Target/RegisterContext.h"
22
23 using namespace lldb;
24 using namespace lldb_private;
25
26 //----------------------------------------------------------------------
27 // ThreadPlanRunToAddress: Continue plan
28 //----------------------------------------------------------------------
29
ThreadPlanRunToAddress(Thread & thread,Address & address,bool stop_others)30 ThreadPlanRunToAddress::ThreadPlanRunToAddress
31 (
32 Thread &thread,
33 Address &address,
34 bool stop_others
35 ) :
36 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
37 m_stop_others (stop_others),
38 m_addresses (),
39 m_break_ids ()
40 {
41 m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get()));
42 SetInitialBreakpoints();
43 }
44
ThreadPlanRunToAddress(Thread & thread,lldb::addr_t address,bool stop_others)45 ThreadPlanRunToAddress::ThreadPlanRunToAddress
46 (
47 Thread &thread,
48 lldb::addr_t address,
49 bool stop_others
50 ) :
51 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
52 m_stop_others (stop_others),
53 m_addresses (),
54 m_break_ids ()
55 {
56 m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
57 SetInitialBreakpoints();
58 }
59
ThreadPlanRunToAddress(Thread & thread,const std::vector<lldb::addr_t> & addresses,bool stop_others)60 ThreadPlanRunToAddress::ThreadPlanRunToAddress
61 (
62 Thread &thread,
63 const std::vector<lldb::addr_t> &addresses,
64 bool stop_others
65 ) :
66 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
67 m_stop_others (stop_others),
68 m_addresses (addresses),
69 m_break_ids ()
70 {
71 // Convert all addresses into opcode addresses to make sure we set
72 // breakpoints at the correct address.
73 Target &target = thread.GetProcess()->GetTarget();
74 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
75 for (pos = m_addresses.begin(); pos != end; ++pos)
76 *pos = target.GetOpcodeLoadAddress (*pos);
77
78 SetInitialBreakpoints();
79 }
80
81 void
SetInitialBreakpoints()82 ThreadPlanRunToAddress::SetInitialBreakpoints ()
83 {
84 size_t num_addresses = m_addresses.size();
85 m_break_ids.resize(num_addresses);
86
87 for (size_t i = 0; i < num_addresses; i++)
88 {
89 Breakpoint *breakpoint;
90 breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get();
91 if (breakpoint != NULL)
92 {
93 m_break_ids[i] = breakpoint->GetID();
94 breakpoint->SetThreadID(m_thread.GetID());
95 breakpoint->SetBreakpointKind("run-to-address");
96 }
97 }
98 }
99
~ThreadPlanRunToAddress()100 ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
101 {
102 size_t num_break_ids = m_break_ids.size();
103 for (size_t i = 0; i < num_break_ids; i++)
104 {
105 m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
106 }
107 }
108
109 void
GetDescription(Stream * s,lldb::DescriptionLevel level)110 ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
111 {
112 size_t num_addresses = m_addresses.size();
113
114 if (level == lldb::eDescriptionLevelBrief)
115 {
116 if (num_addresses == 0)
117 {
118 s->Printf ("run to address with no addresses given.");
119 return;
120 }
121 else if (num_addresses == 1)
122 s->Printf ("run to address: ");
123 else
124 s->Printf ("run to addresses: ");
125
126 for (size_t i = 0; i < num_addresses; i++)
127 {
128 s->Address (m_addresses[i], sizeof (addr_t));
129 s->Printf(" ");
130 }
131 }
132 else
133 {
134 if (num_addresses == 0)
135 {
136 s->Printf ("run to address with no addresses given.");
137 return;
138 }
139 else if (num_addresses == 1)
140 s->Printf ("Run to address: ");
141 else
142 {
143 s->Printf ("Run to addresses: ");
144 }
145
146 for (size_t i = 0; i < num_addresses; i++)
147 {
148 if (num_addresses > 1)
149 {
150 s->Printf("\n");
151 s->Indent();
152 }
153
154 s->Address(m_addresses[i], sizeof (addr_t));
155 s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
156 Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get();
157 if (breakpoint)
158 breakpoint->Dump (s);
159 else
160 s->Printf ("but the breakpoint has been deleted.");
161 }
162 }
163 }
164
165 bool
ValidatePlan(Stream * error)166 ThreadPlanRunToAddress::ValidatePlan (Stream *error)
167 {
168 // If we couldn't set the breakpoint for some reason, then this won't
169 // work.
170 bool all_bps_good = true;
171 size_t num_break_ids = m_break_ids.size();
172
173 for (size_t i = 0; i < num_break_ids; i++)
174 {
175 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
176 {
177 all_bps_good = false;
178 if (error)
179 {
180 error->Printf ("Could not set breakpoint for address: ");
181 error->Address (m_addresses[i], sizeof (addr_t));
182 error->Printf ("\n");
183 }
184 }
185 }
186 return all_bps_good;
187 }
188
189 bool
DoPlanExplainsStop(Event * event_ptr)190 ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
191 {
192 return AtOurAddress();
193 }
194
195 bool
ShouldStop(Event * event_ptr)196 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
197 {
198 return false;
199 }
200
201 bool
StopOthers()202 ThreadPlanRunToAddress::StopOthers ()
203 {
204 return m_stop_others;
205 }
206
207 void
SetStopOthers(bool new_value)208 ThreadPlanRunToAddress::SetStopOthers (bool new_value)
209 {
210 m_stop_others = new_value;
211 }
212
213 StateType
GetPlanRunState()214 ThreadPlanRunToAddress::GetPlanRunState ()
215 {
216 return eStateRunning;
217 }
218
219 bool
WillStop()220 ThreadPlanRunToAddress::WillStop ()
221 {
222 return true;
223 }
224
225 bool
MischiefManaged()226 ThreadPlanRunToAddress::MischiefManaged ()
227 {
228 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
229
230 if (AtOurAddress())
231 {
232 // Remove the breakpoint
233 size_t num_break_ids = m_break_ids.size();
234
235 for (size_t i = 0; i < num_break_ids; i++)
236 {
237 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
238 {
239 m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
240 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
241 }
242 }
243 if (log)
244 log->Printf("Completed run to address plan.");
245 ThreadPlan::MischiefManaged ();
246 return true;
247 }
248 else
249 return false;
250 }
251
252 bool
AtOurAddress()253 ThreadPlanRunToAddress::AtOurAddress ()
254 {
255 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
256 bool found_it = false;
257 size_t num_addresses = m_addresses.size();
258 for (size_t i = 0; i < num_addresses; i++)
259 {
260 if (m_addresses[i] == current_address)
261 {
262 found_it = true;
263 break;
264 }
265 }
266 return found_it;
267 }
268