blob: a9587107a41850c3acf8c414d3e60ed56047c41c [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"
Greg Clayton640dc6b2010-11-18 18:52:36 +000019#include "lldb/Breakpoint/Breakpoint.h"
Greg Clayton643ee732010-08-04 01:40:35 +000020#include "lldb/Breakpoint/BreakpointLocation.h"
21#include "lldb/Breakpoint/StoppointCallbackContext.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Target/Thread.h"
24#include "lldb/Target/ThreadPlan.h"
25#include "lldb/Target/Process.h"
26#include "lldb/Target/UnixSignals.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31StopInfo::StopInfo (Thread &thread, uint64_t value) :
32 m_thread (thread),
33 m_stop_id (thread.GetProcess().GetStopID()),
34 m_value (value)
35{
36}
37
38bool
39StopInfo::IsValid () const
40{
41 return m_thread.GetProcess().GetStopID() == m_stop_id;
42}
43
Jim Ingham15dcb7c2011-01-20 02:03:18 +000044void
45StopInfo::MakeStopInfoValid ()
46{
47 m_stop_id = m_thread.GetProcess().GetStopID();
48}
49
Greg Clayton643ee732010-08-04 01:40:35 +000050//----------------------------------------------------------------------
51// StopInfoBreakpoint
52//----------------------------------------------------------------------
53
54class StopInfoBreakpoint : public StopInfo
55{
56public:
57
58 StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
59 StopInfo (thread, break_id),
60 m_description(),
61 m_should_stop (false),
Jim Inghamf9f40c22011-02-08 05:20:59 +000062 m_should_stop_is_valid (false),
63 m_should_perform_action (true)
Greg Clayton643ee732010-08-04 01:40:35 +000064 {
65 }
66
Jim Inghamd1686902010-10-14 23:45:03 +000067 StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
68 StopInfo (thread, break_id),
69 m_description(),
70 m_should_stop (should_stop),
Jim Inghamf9f40c22011-02-08 05:20:59 +000071 m_should_stop_is_valid (true),
72 m_should_perform_action (true)
Jim Inghamd1686902010-10-14 23:45:03 +000073 {
74 }
75
Greg Clayton643ee732010-08-04 01:40:35 +000076 virtual ~StopInfoBreakpoint ()
77 {
78 }
79
80 virtual StopReason
81 GetStopReason () const
82 {
83 return eStopReasonBreakpoint;
84 }
85
86 virtual bool
87 ShouldStop (Event *event_ptr)
88 {
89 if (!m_should_stop_is_valid)
90 {
91 // Only check once if we should stop at a breakpoint
92 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
93 if (bp_site_sp)
94 {
95 StoppointCallbackContext context (event_ptr,
96 &m_thread.GetProcess(),
97 &m_thread,
98 m_thread.GetStackFrameAtIndex(0).get(),
Jim Ingham7508e732010-08-09 23:31:02 +000099 true);
Greg Clayton643ee732010-08-04 01:40:35 +0000100
101 m_should_stop = bp_site_sp->ShouldStop (&context);
102 }
103 else
104 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000105 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Greg Clayton643ee732010-08-04 01:40:35 +0000106
107 if (log)
108 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
109
110 m_should_stop = true;
111 }
112 m_should_stop_is_valid = true;
113 }
114 return m_should_stop;
115 }
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000116
117 virtual void
118 PerformAction (Event *event_ptr)
119 {
Jim Inghamf9f40c22011-02-08 05:20:59 +0000120 if (!m_should_perform_action)
121 return;
122 m_should_perform_action = false;
123
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000124 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
125 if (bp_site_sp)
126 {
127 size_t num_owners = bp_site_sp->GetNumberOfOwners();
128 for (size_t j = 0; j < num_owners; j++)
129 {
130 // The breakpoint action is an asynchronous breakpoint callback. If we ever need to have both
131 // callbacks and actions on the same breakpoint, we'll have to split this into two.
132 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
133 StoppointCallbackContext context (event_ptr,
134 &m_thread.GetProcess(),
135 &m_thread,
136 m_thread.GetStackFrameAtIndex(0).get(),
137 false);
138 bp_loc_sp->InvokeCallback (&context);
139 }
140 }
141 else
142 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000143 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000144
145 if (log)
146 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
147 }
148 }
Greg Clayton643ee732010-08-04 01:40:35 +0000149
150 virtual bool
151 ShouldNotify (Event *event_ptr)
152 {
153 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
154 if (bp_site_sp)
155 {
156 bool all_internal = true;
157
158 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
159 {
160 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
161 {
162 all_internal = false;
163 break;
164 }
165 }
166 return all_internal == false;
167 }
168 return true;
169 }
170
171 virtual const char *
172 GetDescription ()
173 {
174 if (m_description.empty())
175 {
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000176 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
177 if (bp_site_sp)
178 {
179 StreamString strm;
180 strm.Printf("breakpoint ");
181 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
182 m_description.swap (strm.GetString());
183 }
184 else
185 {
186 StreamString strm;
187 strm.Printf("breakpoint site %lli", m_value);
188 m_description.swap (strm.GetString());
189 }
Greg Clayton643ee732010-08-04 01:40:35 +0000190 }
191 return m_description.c_str();
192 }
193
194private:
195 std::string m_description;
196 bool m_should_stop;
197 bool m_should_stop_is_valid;
Jim Inghamf9f40c22011-02-08 05:20:59 +0000198 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions
199 // etc. behind the users backs, we need to make sure we only REALLY perform the action once.
Greg Clayton643ee732010-08-04 01:40:35 +0000200};
201
202
203//----------------------------------------------------------------------
204// StopInfoWatchpoint
205//----------------------------------------------------------------------
206
207class StopInfoWatchpoint : public StopInfo
208{
209public:
210
211 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
212 StopInfo (thread, watch_id),
213 m_description()
214 {
215 }
216
217 virtual ~StopInfoWatchpoint ()
218 {
219 }
220
221 virtual StopReason
222 GetStopReason () const
223 {
224 return eStopReasonWatchpoint;
225 }
226
227 virtual const char *
228 GetDescription ()
229 {
230 if (m_description.empty())
231 {
232 StreamString strm;
233 strm.Printf("watchpoint %lli", m_value);
234 m_description.swap (strm.GetString());
235 }
236 return m_description.c_str();
237 }
238
239
240
241private:
242 std::string m_description;
243};
244
245
246
247//----------------------------------------------------------------------
248// StopInfoUnixSignal
249//----------------------------------------------------------------------
250
251class StopInfoUnixSignal : public StopInfo
252{
253public:
254
255 StopInfoUnixSignal (Thread &thread, int signo) :
Greg Clayton65611552011-06-04 01:26:29 +0000256 StopInfo (thread, signo)
Greg Clayton643ee732010-08-04 01:40:35 +0000257 {
258 }
259
260 virtual ~StopInfoUnixSignal ()
261 {
262 }
263
264
265 virtual StopReason
266 GetStopReason () const
267 {
268 return eStopReasonSignal;
269 }
270
271 virtual bool
272 ShouldStop (Event *event_ptr)
273 {
274 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value);
275 }
276
277
278 // If should stop returns false, check if we should notify of this event
279 virtual bool
280 ShouldNotify (Event *event_ptr)
281 {
282 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value);
283 }
284
285
286 virtual void
287 WillResume (lldb::StateType resume_state)
288 {
289 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false)
290 m_thread.SetResumeSignal(m_value);
291 }
292
293 virtual const char *
294 GetDescription ()
295 {
296 if (m_description.empty())
297 {
298 StreamString strm;
299 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value);
300 if (signal_name)
Greg Claytona830adb2010-10-04 01:05:56 +0000301 strm.Printf("signal %s", signal_name);
Greg Clayton643ee732010-08-04 01:40:35 +0000302 else
Greg Claytona830adb2010-10-04 01:05:56 +0000303 strm.Printf("signal %lli", m_value);
Greg Clayton643ee732010-08-04 01:40:35 +0000304 m_description.swap (strm.GetString());
305 }
306 return m_description.c_str();
307 }
Greg Clayton643ee732010-08-04 01:40:35 +0000308};
309
310//----------------------------------------------------------------------
311// StopInfoTrace
312//----------------------------------------------------------------------
313
314class StopInfoTrace : public StopInfo
315{
316public:
317
318 StopInfoTrace (Thread &thread) :
319 StopInfo (thread, LLDB_INVALID_UID)
320 {
321 }
322
323 virtual ~StopInfoTrace ()
324 {
325 }
326
327 virtual StopReason
328 GetStopReason () const
329 {
330 return eStopReasonTrace;
331 }
332
333 virtual const char *
334 GetDescription ()
335 {
Greg Clayton65611552011-06-04 01:26:29 +0000336 if (m_description.empty())
Greg Clayton643ee732010-08-04 01:40:35 +0000337 return "trace";
Greg Clayton65611552011-06-04 01:26:29 +0000338 else
339 return m_description.c_str();
340 }
341};
342
343
344//----------------------------------------------------------------------
345// StopInfoException
346//----------------------------------------------------------------------
347
348class StopInfoException : public StopInfo
349{
350public:
351
352 StopInfoException (Thread &thread, const char *description) :
353 StopInfo (thread, LLDB_INVALID_UID)
354 {
355 if (description)
356 SetDescription (description);
357 }
358
359 virtual
360 ~StopInfoException ()
361 {
362 }
363
364 virtual StopReason
365 GetStopReason () const
366 {
367 return eStopReasonException;
368 }
369
370 virtual const char *
371 GetDescription ()
372 {
373 if (m_description.empty())
374 return "exception";
375 else
376 return m_description.c_str();
Greg Clayton643ee732010-08-04 01:40:35 +0000377 }
378};
379
380
381//----------------------------------------------------------------------
382// StopInfoThreadPlan
383//----------------------------------------------------------------------
384
385class StopInfoThreadPlan : public StopInfo
386{
387public:
388
389 StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
390 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
391 m_plan_sp (plan_sp)
392 {
393 }
394
395 virtual ~StopInfoThreadPlan ()
396 {
397 }
398
399 virtual StopReason
400 GetStopReason () const
401 {
402 return eStopReasonPlanComplete;
403 }
404
405 virtual const char *
406 GetDescription ()
407 {
408 if (m_description.empty())
409 {
410 StreamString strm;
411 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
412 m_description.swap (strm.GetString());
413 }
414 return m_description.c_str();
415 }
416
417private:
418 ThreadPlanSP m_plan_sp;
Greg Clayton643ee732010-08-04 01:40:35 +0000419};
420
421StopInfoSP
422StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
423{
424 return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
425}
426
427StopInfoSP
Jim Inghamd1686902010-10-14 23:45:03 +0000428StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
429{
430 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
431}
432
433StopInfoSP
Greg Clayton643ee732010-08-04 01:40:35 +0000434StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
435{
436 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
437}
438
439StopInfoSP
440StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo)
441{
442 return StopInfoSP (new StopInfoUnixSignal (thread, signo));
443}
444
445StopInfoSP
446StopInfo::CreateStopReasonToTrace (Thread &thread)
447{
448 return StopInfoSP (new StopInfoTrace (thread));
449}
450
451StopInfoSP
452StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
453{
454 return StopInfoSP (new StopInfoThreadPlan (plan_sp));
455}
Greg Clayton65611552011-06-04 01:26:29 +0000456
457StopInfoSP
458StopInfo::CreateStopReasonWithException (Thread &thread, const char *description)
459{
460 return StopInfoSP (new StopInfoException (thread, description));
461}