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 
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 
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 
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
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 
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
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
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
190 ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
191 {
192     return AtOurAddress();
193 }
194 
195 bool
196 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
197 {
198     return AtOurAddress();
199 }
200 
201 bool
202 ThreadPlanRunToAddress::StopOthers ()
203 {
204     return m_stop_others;
205 }
206 
207 void
208 ThreadPlanRunToAddress::SetStopOthers (bool new_value)
209 {
210     m_stop_others = new_value;
211 }
212 
213 StateType
214 ThreadPlanRunToAddress::GetPlanRunState ()
215 {
216     return eStateRunning;
217 }
218 
219 bool
220 ThreadPlanRunToAddress::WillStop ()
221 {
222     return true;
223 }
224 
225 bool
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
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