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