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