blob: d301cc156ff257b04d03a4c31263c9896930da2e [file] [log] [blame]
Greg Clayton643ee732010-08-04 01:40:35 +00001//===-- StopInfo.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/StopInfo.h"
11
12// C Includes
13// C++ Includes
14#include <string>
15
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/Log.h"
19#include "lldb/Breakpoint/BreakpointLocation.h"
20#include "lldb/Breakpoint/StoppointCallbackContext.h"
21#include "lldb/Core/StreamString.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Target/ThreadPlan.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/UnixSignals.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30StopInfo::StopInfo (Thread &thread, uint64_t value) :
31 m_thread (thread),
32 m_stop_id (thread.GetProcess().GetStopID()),
33 m_value (value)
34{
35}
36
37bool
38StopInfo::IsValid () const
39{
40 return m_thread.GetProcess().GetStopID() == m_stop_id;
41}
42
43//----------------------------------------------------------------------
44// StopInfoBreakpoint
45//----------------------------------------------------------------------
46
47class StopInfoBreakpoint : public StopInfo
48{
49public:
50
51 StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
52 StopInfo (thread, break_id),
53 m_description(),
54 m_should_stop (false),
55 m_should_stop_is_valid (false)
56 {
57 }
58
59 virtual ~StopInfoBreakpoint ()
60 {
61 }
62
63 virtual StopReason
64 GetStopReason () const
65 {
66 return eStopReasonBreakpoint;
67 }
68
69 virtual bool
70 ShouldStop (Event *event_ptr)
71 {
72 if (!m_should_stop_is_valid)
73 {
74 // Only check once if we should stop at a breakpoint
75 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
76 if (bp_site_sp)
77 {
78 StoppointCallbackContext context (event_ptr,
79 &m_thread.GetProcess(),
80 &m_thread,
81 m_thread.GetStackFrameAtIndex(0).get(),
Jim Ingham7508e732010-08-09 23:31:02 +000082 true);
Greg Clayton643ee732010-08-04 01:40:35 +000083
84 m_should_stop = bp_site_sp->ShouldStop (&context);
85 }
86 else
87 {
88 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
89
90 if (log)
91 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
92
93 m_should_stop = true;
94 }
95 m_should_stop_is_valid = true;
96 }
97 return m_should_stop;
98 }
Jim Ingham6fb8baa2010-08-10 00:59:59 +000099
100 virtual void
101 PerformAction (Event *event_ptr)
102 {
103 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
104 if (bp_site_sp)
105 {
106 size_t num_owners = bp_site_sp->GetNumberOfOwners();
107 for (size_t j = 0; j < num_owners; j++)
108 {
109 // The breakpoint action is an asynchronous breakpoint callback. If we ever need to have both
110 // callbacks and actions on the same breakpoint, we'll have to split this into two.
111 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
112 StoppointCallbackContext context (event_ptr,
113 &m_thread.GetProcess(),
114 &m_thread,
115 m_thread.GetStackFrameAtIndex(0).get(),
116 false);
117 bp_loc_sp->InvokeCallback (&context);
118 }
119 }
120 else
121 {
122 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
123
124 if (log)
125 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
126 }
127 }
Greg Clayton643ee732010-08-04 01:40:35 +0000128
129 virtual bool
130 ShouldNotify (Event *event_ptr)
131 {
132 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
133 if (bp_site_sp)
134 {
135 bool all_internal = true;
136
137 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
138 {
139 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
140 {
141 all_internal = false;
142 break;
143 }
144 }
145 return all_internal == false;
146 }
147 return true;
148 }
149
150 virtual const char *
151 GetDescription ()
152 {
153 if (m_description.empty())
154 {
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000155 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
156 if (bp_site_sp)
157 {
158 StreamString strm;
159 strm.Printf("breakpoint ");
160 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
161 m_description.swap (strm.GetString());
162 }
163 else
164 {
165 StreamString strm;
166 strm.Printf("breakpoint site %lli", m_value);
167 m_description.swap (strm.GetString());
168 }
Greg Clayton643ee732010-08-04 01:40:35 +0000169 }
170 return m_description.c_str();
171 }
172
173private:
174 std::string m_description;
175 bool m_should_stop;
176 bool m_should_stop_is_valid;
177};
178
179
180//----------------------------------------------------------------------
181// StopInfoWatchpoint
182//----------------------------------------------------------------------
183
184class StopInfoWatchpoint : public StopInfo
185{
186public:
187
188 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
189 StopInfo (thread, watch_id),
190 m_description()
191 {
192 }
193
194 virtual ~StopInfoWatchpoint ()
195 {
196 }
197
198 virtual StopReason
199 GetStopReason () const
200 {
201 return eStopReasonWatchpoint;
202 }
203
204 virtual const char *
205 GetDescription ()
206 {
207 if (m_description.empty())
208 {
209 StreamString strm;
210 strm.Printf("watchpoint %lli", m_value);
211 m_description.swap (strm.GetString());
212 }
213 return m_description.c_str();
214 }
215
216
217
218private:
219 std::string m_description;
220};
221
222
223
224//----------------------------------------------------------------------
225// StopInfoUnixSignal
226//----------------------------------------------------------------------
227
228class StopInfoUnixSignal : public StopInfo
229{
230public:
231
232 StopInfoUnixSignal (Thread &thread, int signo) :
233 StopInfo (thread, signo),
234 m_description()
235 {
236 }
237
238 virtual ~StopInfoUnixSignal ()
239 {
240 }
241
242
243 virtual StopReason
244 GetStopReason () const
245 {
246 return eStopReasonSignal;
247 }
248
249 virtual bool
250 ShouldStop (Event *event_ptr)
251 {
252 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value);
253 }
254
255
256 // If should stop returns false, check if we should notify of this event
257 virtual bool
258 ShouldNotify (Event *event_ptr)
259 {
260 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value);
261 }
262
263
264 virtual void
265 WillResume (lldb::StateType resume_state)
266 {
267 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false)
268 m_thread.SetResumeSignal(m_value);
269 }
270
271 virtual const char *
272 GetDescription ()
273 {
274 if (m_description.empty())
275 {
276 StreamString strm;
277 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value);
278 if (signal_name)
279 strm.Printf("signal = %s", signal_name);
280 else
281 strm.Printf("signal = %lli", m_value);
282 m_description.swap (strm.GetString());
283 }
284 return m_description.c_str();
285 }
286
287private:
288 std::string m_description;
289};
290
291//----------------------------------------------------------------------
292// StopInfoTrace
293//----------------------------------------------------------------------
294
295class StopInfoTrace : public StopInfo
296{
297public:
298
299 StopInfoTrace (Thread &thread) :
300 StopInfo (thread, LLDB_INVALID_UID)
301 {
302 }
303
304 virtual ~StopInfoTrace ()
305 {
306 }
307
308 virtual StopReason
309 GetStopReason () const
310 {
311 return eStopReasonTrace;
312 }
313
314 virtual const char *
315 GetDescription ()
316 {
317 return "trace";
318 }
319};
320
321
322//----------------------------------------------------------------------
323// StopInfoThreadPlan
324//----------------------------------------------------------------------
325
326class StopInfoThreadPlan : public StopInfo
327{
328public:
329
330 StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
331 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
332 m_plan_sp (plan_sp)
333 {
334 }
335
336 virtual ~StopInfoThreadPlan ()
337 {
338 }
339
340 virtual StopReason
341 GetStopReason () const
342 {
343 return eStopReasonPlanComplete;
344 }
345
346 virtual const char *
347 GetDescription ()
348 {
349 if (m_description.empty())
350 {
351 StreamString strm;
352 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
353 m_description.swap (strm.GetString());
354 }
355 return m_description.c_str();
356 }
357
358private:
359 ThreadPlanSP m_plan_sp;
360 std::string m_description;
361};
362
363StopInfoSP
364StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
365{
366 return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
367}
368
369StopInfoSP
370StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
371{
372 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
373}
374
375StopInfoSP
376StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo)
377{
378 return StopInfoSP (new StopInfoUnixSignal (thread, signo));
379}
380
381StopInfoSP
382StopInfo::CreateStopReasonToTrace (Thread &thread)
383{
384 return StopInfoSP (new StopInfoTrace (thread));
385}
386
387StopInfoSP
388StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
389{
390 return StopInfoSP (new StopInfoThreadPlan (plan_sp));
391}