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             error->Printf ("Could not set breakpoint for address: ");
172             error->Address (m_addresses[i], sizeof (addr_t));
173             error->Printf ("\n");
174         }
175     }
176     return all_bps_good;
177 }
178 
179 bool
180 ThreadPlanRunToAddress::PlanExplainsStop ()
181 {
182     return AtOurAddress();
183 }
184 
185 bool
186 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
187 {
188     return false;
189 }
190 
191 bool
192 ThreadPlanRunToAddress::StopOthers ()
193 {
194     return m_stop_others;
195 }
196 
197 void
198 ThreadPlanRunToAddress::SetStopOthers (bool new_value)
199 {
200     m_stop_others = new_value;
201 }
202 
203 StateType
204 ThreadPlanRunToAddress::RunState ()
205 {
206     return eStateRunning;
207 }
208 
209 bool
210 ThreadPlanRunToAddress::WillStop ()
211 {
212     return true;
213 }
214 
215 bool
216 ThreadPlanRunToAddress::MischiefManaged ()
217 {
218     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
219 
220     if (AtOurAddress())
221     {
222         // Remove the breakpoint
223         size_t num_break_ids = m_break_ids.size();
224 
225         for (size_t i = 0; i < num_break_ids; i++)
226         {
227             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
228             {
229                 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
230                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
231             }
232         }
233         if (log)
234             log->Printf("Completed run to address plan.");
235         ThreadPlan::MischiefManaged ();
236         return true;
237     }
238     else
239         return false;
240 }
241 
242 bool
243 ThreadPlanRunToAddress::AtOurAddress ()
244 {
245     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
246     bool found_it = false;
247     for (size_t i = 0; i < m_addresses[i]; i++)
248     {
249         if (m_addresses[i] == current_address)
250         {
251             found_it = true;
252             break;
253         }
254     }
255     return found_it;
256 }
257