blob: 3203ec8b52aa68f324e3eddab29bcb0da05252e8 [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"
Johnny Chenecd4feb2011-10-14 00:42:25 +000022#include "lldb/Breakpoint/Watchpoint.h"
Jim Ingham21f37ad2011-08-09 02:12:22 +000023#include "lldb/Core/Debugger.h"
Greg Clayton643ee732010-08-04 01:40:35 +000024#include "lldb/Core/StreamString.h"
Jim Ingham21f37ad2011-08-09 02:12:22 +000025#include "lldb/Expression/ClangUserExpression.h"
26#include "lldb/Target/Target.h"
Greg Clayton643ee732010-08-04 01:40:35 +000027#include "lldb/Target/Thread.h"
28#include "lldb/Target/ThreadPlan.h"
29#include "lldb/Target/Process.h"
30#include "lldb/Target/UnixSignals.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35StopInfo::StopInfo (Thread &thread, uint64_t value) :
36 m_thread (thread),
37 m_stop_id (thread.GetProcess().GetStopID()),
Jim Ingham0296fe72011-11-08 03:00:11 +000038 m_resume_id (thread.GetProcess().GetResumeID()),
Greg Clayton643ee732010-08-04 01:40:35 +000039 m_value (value)
40{
41}
42
43bool
44StopInfo::IsValid () const
45{
46 return m_thread.GetProcess().GetStopID() == m_stop_id;
47}
48
Jim Ingham15dcb7c2011-01-20 02:03:18 +000049void
50StopInfo::MakeStopInfoValid ()
51{
52 m_stop_id = m_thread.GetProcess().GetStopID();
Jim Ingham0296fe72011-11-08 03:00:11 +000053 m_resume_id = m_thread.GetProcess().GetResumeID();
Jim Ingham15dcb7c2011-01-20 02:03:18 +000054}
55
Jim Ingham0296fe72011-11-08 03:00:11 +000056bool
57StopInfo::HasTargetRunSinceMe ()
Jim Ingham21f37ad2011-08-09 02:12:22 +000058{
Jim Ingham0296fe72011-11-08 03:00:11 +000059 lldb::StateType ret_type = m_thread.GetProcess().GetPrivateState();
60 if (ret_type == eStateRunning)
61 {
62 return true;
63 }
64 else if (ret_type == eStateStopped)
65 {
66 // This is a little tricky. We want to count "run and stopped again before you could
67 // ask this question as a "TRUE" answer to HasTargetRunSinceMe. But we don't want to
68 // include any running of the target done for expressions. So we track both resumes,
69 // and resumes caused by expressions, and check if there are any resumes NOT caused
70 // by expressions.
71
72 uint32_t curr_resume_id = m_thread.GetProcess().GetResumeID();
73 uint32_t last_user_expression_id = m_thread.GetProcess().GetLastUserExpressionResumeID ();
74 if (curr_resume_id == m_resume_id)
75 {
76 return false;
77 }
78 else if (curr_resume_id > last_user_expression_id)
79 {
80 return true;
81 }
82 }
83 return false;
Jim Ingham21f37ad2011-08-09 02:12:22 +000084}
85
Greg Clayton643ee732010-08-04 01:40:35 +000086//----------------------------------------------------------------------
87// StopInfoBreakpoint
88//----------------------------------------------------------------------
89
Jim Ingham21f37ad2011-08-09 02:12:22 +000090namespace lldb_private
91{
Greg Clayton643ee732010-08-04 01:40:35 +000092class StopInfoBreakpoint : public StopInfo
93{
94public:
95
96 StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
97 StopInfo (thread, break_id),
98 m_description(),
99 m_should_stop (false),
Jim Inghamf9f40c22011-02-08 05:20:59 +0000100 m_should_stop_is_valid (false),
Jim Ingham1c658532011-10-28 01:12:19 +0000101 m_should_perform_action (true),
102 m_address (LLDB_INVALID_ADDRESS)
Greg Clayton643ee732010-08-04 01:40:35 +0000103 {
Jim Ingham1c658532011-10-28 01:12:19 +0000104 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
105 if (bp_site_sp)
106 {
107 m_address = bp_site_sp->GetLoadAddress();
108 }
Greg Clayton643ee732010-08-04 01:40:35 +0000109 }
110
Jim Inghamd1686902010-10-14 23:45:03 +0000111 StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
112 StopInfo (thread, break_id),
113 m_description(),
114 m_should_stop (should_stop),
Jim Inghamf9f40c22011-02-08 05:20:59 +0000115 m_should_stop_is_valid (true),
Jim Ingham1c658532011-10-28 01:12:19 +0000116 m_should_perform_action (true),
117 m_address (LLDB_INVALID_ADDRESS)
Jim Inghamd1686902010-10-14 23:45:03 +0000118 {
Jim Ingham1c658532011-10-28 01:12:19 +0000119 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
120 if (bp_site_sp)
121 {
122 m_address = bp_site_sp->GetLoadAddress();
123 }
Jim Inghamd1686902010-10-14 23:45:03 +0000124 }
125
Greg Clayton643ee732010-08-04 01:40:35 +0000126 virtual ~StopInfoBreakpoint ()
127 {
128 }
129
130 virtual StopReason
131 GetStopReason () const
132 {
133 return eStopReasonBreakpoint;
134 }
135
136 virtual bool
137 ShouldStop (Event *event_ptr)
138 {
139 if (!m_should_stop_is_valid)
140 {
141 // Only check once if we should stop at a breakpoint
142 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
143 if (bp_site_sp)
144 {
145 StoppointCallbackContext context (event_ptr,
146 &m_thread.GetProcess(),
147 &m_thread,
148 m_thread.GetStackFrameAtIndex(0).get(),
Jim Ingham7508e732010-08-09 23:31:02 +0000149 true);
Greg Clayton643ee732010-08-04 01:40:35 +0000150
151 m_should_stop = bp_site_sp->ShouldStop (&context);
152 }
153 else
154 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000155 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Greg Clayton643ee732010-08-04 01:40:35 +0000156
157 if (log)
158 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
159
160 m_should_stop = true;
161 }
162 m_should_stop_is_valid = true;
163 }
164 return m_should_stop;
165 }
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000166
167 virtual void
168 PerformAction (Event *event_ptr)
169 {
Jim Inghamf9f40c22011-02-08 05:20:59 +0000170 if (!m_should_perform_action)
171 return;
172 m_should_perform_action = false;
173
Jim Ingham21f37ad2011-08-09 02:12:22 +0000174 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
175 // We're going to calculate whether we should stop or not in some way during the course of
176 // this code. So set the valid flag here. Also by default we're going to stop, so
177 // set that here too.
178 // m_should_stop_is_valid = true;
179 m_should_stop = true;
180
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000181 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
182 if (bp_site_sp)
183 {
184 size_t num_owners = bp_site_sp->GetNumberOfOwners();
Jim Ingham21f37ad2011-08-09 02:12:22 +0000185
186 // We only continue from the callbacks if ALL the callbacks want us to continue.
187 // However we want to run all the callbacks, except of course if one of them actually
188 // resumes the target.
189 // So we use stop_requested to track what we're were asked to do.
Jim Ingham0296fe72011-11-08 03:00:11 +0000190 bool stop_requested = false;
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000191 for (size_t j = 0; j < num_owners; j++)
192 {
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000193 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
194 StoppointCallbackContext context (event_ptr,
195 &m_thread.GetProcess(),
196 &m_thread,
197 m_thread.GetStackFrameAtIndex(0).get(),
198 false);
Jim Ingham0296fe72011-11-08 03:00:11 +0000199 bool callback_return;
200
201 // FIXME: For now the callbacks have to run in async mode - the first time we restart we need
202 // to get out of there. So set it here.
203 // When we figure out how to stack breakpoint hits then this will change.
204
205 Debugger &debugger = m_thread.GetProcess().GetTarget().GetDebugger();
206 bool old_async = debugger.GetAsyncExecution();
207 debugger.SetAsyncExecution (true);
208
209 callback_return = bp_loc_sp->InvokeCallback (&context);
210
211 debugger.SetAsyncExecution (old_async);
212
213 if (callback_return)
214 stop_requested = true;
215
Jim Ingham21f37ad2011-08-09 02:12:22 +0000216 // Also make sure that the callback hasn't continued the target.
217 // If it did, when we'll set m_should_start to false and get out of here.
Jim Ingham0296fe72011-11-08 03:00:11 +0000218 if (HasTargetRunSinceMe ())
219 {
Jim Ingham21f37ad2011-08-09 02:12:22 +0000220 m_should_stop = false;
Jim Ingham0296fe72011-11-08 03:00:11 +0000221 break;
222 }
Jim Ingham21f37ad2011-08-09 02:12:22 +0000223 }
224
225 if (m_should_stop && !stop_requested)
226 {
227 m_should_stop_is_valid = true;
228 m_should_stop = false;
229 }
230
231 // Okay, so now if all the callbacks say we should stop, let's try the Conditions:
232 if (m_should_stop)
233 {
234 size_t num_owners = bp_site_sp->GetNumberOfOwners();
235 for (size_t j = 0; j < num_owners; j++)
236 {
237 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
238 if (bp_loc_sp->GetConditionText() != NULL)
239 {
240 // We need to make sure the user sees any parse errors in their condition, so we'll hook the
241 // constructor errors up to the debugger's Async I/O.
242
243 StoppointCallbackContext context (event_ptr,
244 &m_thread.GetProcess(),
245 &m_thread,
246 m_thread.GetStackFrameAtIndex(0).get(),
247 false);
248 ValueObjectSP result_valobj_sp;
249
250 ExecutionResults result_code;
251 ValueObjectSP result_value_sp;
252 const bool discard_on_error = true;
253 Error error;
254 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
Sean Callanan47dc4572011-09-15 02:13:07 +0000255 eExecutionPolicyAlways,
Sean Callanan5b658cc2011-11-07 23:35:40 +0000256 lldb::eLanguageTypeUnknown,
Sean Callanan47dc4572011-09-15 02:13:07 +0000257 discard_on_error,
258 bp_loc_sp->GetConditionText(),
259 NULL,
260 result_value_sp,
261 error);
Jim Ingham21f37ad2011-08-09 02:12:22 +0000262 if (result_code == eExecutionCompleted)
263 {
264 if (result_value_sp)
265 {
266 Scalar scalar_value;
267 if (result_value_sp->ResolveValue (scalar_value))
268 {
269 if (scalar_value.ULongLong(1) == 0)
270 m_should_stop = false;
271 else
272 m_should_stop = true;
273 if (log)
274 log->Printf("Condition successfully evaluated, result is %s.\n",
275 m_should_stop ? "true" : "false");
276 }
277 else
278 {
279 m_should_stop = true;
280 if (log)
281 log->Printf("Failed to get an integer result from the expression.");
282 }
283 }
284 }
285 else
286 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000287 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger();
Jim Ingham21f37ad2011-08-09 02:12:22 +0000288 StreamSP error_sp = debugger.GetAsyncErrorStream ();
289 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
290 bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
291 error_sp->Printf (": \"%s\"",
292 bp_loc_sp->GetConditionText());
293 error_sp->EOL();
294 const char *err_str = error.AsCString("<Unknown Error>");
295 if (log)
296 log->Printf("Error evaluating condition: \"%s\"\n", err_str);
297
298 error_sp->PutCString (err_str);
299 error_sp->EOL();
300 error_sp->Flush();
301 // If the condition fails to be parsed or run, we should stop.
302 m_should_stop = true;
303 }
304 }
305
306 // If any condition says we should stop, then we're going to stop, so we don't need
307 // to evaluate the others.
308 if (m_should_stop)
309 break;
310 }
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000311 }
312 }
313 else
314 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000315 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000316
317 if (log)
318 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
319 }
Jim Ingham21f37ad2011-08-09 02:12:22 +0000320 if (log)
321 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000322 }
Greg Clayton643ee732010-08-04 01:40:35 +0000323
324 virtual bool
325 ShouldNotify (Event *event_ptr)
326 {
327 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
328 if (bp_site_sp)
329 {
330 bool all_internal = true;
331
332 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
333 {
334 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
335 {
336 all_internal = false;
337 break;
338 }
339 }
340 return all_internal == false;
341 }
342 return true;
343 }
344
345 virtual const char *
346 GetDescription ()
347 {
348 if (m_description.empty())
349 {
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000350 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
351 if (bp_site_sp)
352 {
353 StreamString strm;
354 strm.Printf("breakpoint ");
355 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
356 m_description.swap (strm.GetString());
357 }
358 else
359 {
360 StreamString strm;
Jim Ingham1c658532011-10-28 01:12:19 +0000361 if (m_address == LLDB_INVALID_ADDRESS)
362 strm.Printf("breakpoint site %lli which has been deleted - unknown address", m_value);
363 else
364 strm.Printf("breakpoint site %lli which has been deleted - was at 0x%llx", m_value, m_address);
Jim Ingham6fb8baa2010-08-10 00:59:59 +0000365 m_description.swap (strm.GetString());
366 }
Greg Clayton643ee732010-08-04 01:40:35 +0000367 }
368 return m_description.c_str();
369 }
370
371private:
372 std::string m_description;
373 bool m_should_stop;
374 bool m_should_stop_is_valid;
Jim Inghamf9f40c22011-02-08 05:20:59 +0000375 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions
376 // etc. behind the users backs, we need to make sure we only REALLY perform the action once.
Jim Ingham1c658532011-10-28 01:12:19 +0000377 lldb::addr_t m_address; // We use this to capture the breakpoint site address when we create the StopInfo,
378 // in case somebody deletes it between the time the StopInfo is made and the
379 // description is asked for.
Greg Clayton643ee732010-08-04 01:40:35 +0000380};
381
382
383//----------------------------------------------------------------------
384// StopInfoWatchpoint
385//----------------------------------------------------------------------
386
387class StopInfoWatchpoint : public StopInfo
388{
389public:
390
391 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
Johnny Chen043f8c22011-09-21 22:47:15 +0000392 StopInfo(thread, watch_id),
393 m_description(),
394 m_should_stop(false),
395 m_should_stop_is_valid(false)
Greg Clayton643ee732010-08-04 01:40:35 +0000396 {
397 }
398
399 virtual ~StopInfoWatchpoint ()
400 {
401 }
402
403 virtual StopReason
404 GetStopReason () const
405 {
406 return eStopReasonWatchpoint;
407 }
408
Johnny Chen043f8c22011-09-21 22:47:15 +0000409 virtual bool
410 ShouldStop (Event *event_ptr)
411 {
412 // ShouldStop() method is idempotent and should not affect hit count.
Johnny Chen712a6282011-10-17 18:58:00 +0000413 // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
414 // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
415 // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
416 // StopInfoWatchpoint::ShouldStop() and
417 // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()->
418 // StopInfoWatchpoint::PerformAction().
Johnny Chen043f8c22011-09-21 22:47:15 +0000419 if (m_should_stop_is_valid)
420 return m_should_stop;
421
Johnny Chenecd4feb2011-10-14 00:42:25 +0000422 WatchpointSP wp_sp =
423 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue());
424 if (wp_sp)
Johnny Chen043f8c22011-09-21 22:47:15 +0000425 {
426 // Check if we should stop at a watchpoint.
427 StoppointCallbackContext context (event_ptr,
428 &m_thread.GetProcess(),
429 &m_thread,
430 m_thread.GetStackFrameAtIndex(0).get(),
431 true);
432
Johnny Chenecd4feb2011-10-14 00:42:25 +0000433 m_should_stop = wp_sp->ShouldStop (&context);
Johnny Chen043f8c22011-09-21 22:47:15 +0000434 }
435 else
436 {
437 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
438
439 if (log)
440 log->Printf ("Process::%s could not find watchpoint location id: %lld...",
441 __FUNCTION__, GetValue());
442
443 m_should_stop = true;
444 }
445 m_should_stop_is_valid = true;
446 return m_should_stop;
447 }
448
Johnny Chen712a6282011-10-17 18:58:00 +0000449 // Perform any action that is associated with this stop. This is done as the
450 // Event is removed from the event queue.
451 virtual void
452 PerformAction (Event *event_ptr)
453 {
454 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
455 // We're going to calculate if we should stop or not in some way during the course of
456 // this code. Also by default we're going to stop, so set that here.
457 m_should_stop = true;
458
459 WatchpointSP wp_sp =
460 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue());
461 if (wp_sp)
462 {
463 StoppointCallbackContext context (event_ptr,
464 &m_thread.GetProcess(),
465 &m_thread,
466 m_thread.GetStackFrameAtIndex(0).get(),
467 false);
468 bool stop_requested = wp_sp->InvokeCallback (&context);
469 // Also make sure that the callback hasn't continued the target.
470 // If it did, when we'll set m_should_start to false and get out of here.
Jim Ingham0296fe72011-11-08 03:00:11 +0000471 if (HasTargetRunSinceMe ())
Johnny Chen712a6282011-10-17 18:58:00 +0000472 m_should_stop = false;
473
474 if (m_should_stop && !stop_requested)
475 {
476 // We have been vetoed.
477 m_should_stop = false;
478 }
479
480 if (m_should_stop && wp_sp->GetConditionText() != NULL)
481 {
482 // We need to make sure the user sees any parse errors in their condition, so we'll hook the
483 // constructor errors up to the debugger's Async I/O.
484 StoppointCallbackContext context (event_ptr,
485 &m_thread.GetProcess(),
486 &m_thread,
487 m_thread.GetStackFrameAtIndex(0).get(),
488 false);
489 ExecutionResults result_code;
490 ValueObjectSP result_value_sp;
491 const bool discard_on_error = true;
492 Error error;
493 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
494 eExecutionPolicyAlways,
Sean Callanan5b658cc2011-11-07 23:35:40 +0000495 lldb::eLanguageTypeUnknown,
Johnny Chen712a6282011-10-17 18:58:00 +0000496 discard_on_error,
497 wp_sp->GetConditionText(),
498 NULL,
499 result_value_sp,
500 error);
501 if (result_code == eExecutionCompleted)
502 {
503 if (result_value_sp)
504 {
505 Scalar scalar_value;
506 if (result_value_sp->ResolveValue (scalar_value))
507 {
508 if (scalar_value.ULongLong(1) == 0)
509 {
510 // We have been vetoed. This takes precedence over querying
511 // the watchpoint whether it should stop (aka ignore count and
512 // friends). See also StopInfoWatchpoint::ShouldStop() as well
513 // as Process::ProcessEventData::DoOnRemoval().
514 m_should_stop = false;
515 }
516 else
517 m_should_stop = true;
518 if (log)
519 log->Printf("Condition successfully evaluated, result is %s.\n",
520 m_should_stop ? "true" : "false");
521 }
522 else
523 {
524 m_should_stop = true;
525 if (log)
526 log->Printf("Failed to get an integer result from the expression.");
527 }
528 }
529 }
530 else
531 {
532 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger();
533 StreamSP error_sp = debugger.GetAsyncErrorStream ();
534 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
535 wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
536 error_sp->Printf (": \"%s\"",
537 wp_sp->GetConditionText());
538 error_sp->EOL();
539 const char *err_str = error.AsCString("<Unknown Error>");
540 if (log)
541 log->Printf("Error evaluating condition: \"%s\"\n", err_str);
542
543 error_sp->PutCString (err_str);
544 error_sp->EOL();
545 error_sp->Flush();
546 // If the condition fails to be parsed or run, we should stop.
547 m_should_stop = true;
548 }
549 }
550 }
551 else
552 {
553 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
554
555 if (log)
556 log->Printf ("Process::%s could not find watchpoint id: %lld...", __FUNCTION__, m_value);
557 }
558 if (log)
559 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
560 }
561
Greg Clayton643ee732010-08-04 01:40:35 +0000562 virtual const char *
563 GetDescription ()
564 {
565 if (m_description.empty())
566 {
567 StreamString strm;
568 strm.Printf("watchpoint %lli", m_value);
569 m_description.swap (strm.GetString());
570 }
571 return m_description.c_str();
572 }
573
Greg Clayton643ee732010-08-04 01:40:35 +0000574private:
575 std::string m_description;
Johnny Chen043f8c22011-09-21 22:47:15 +0000576 bool m_should_stop;
577 bool m_should_stop_is_valid;
Greg Clayton643ee732010-08-04 01:40:35 +0000578};
579
580
581
582//----------------------------------------------------------------------
583// StopInfoUnixSignal
584//----------------------------------------------------------------------
585
586class StopInfoUnixSignal : public StopInfo
587{
588public:
589
590 StopInfoUnixSignal (Thread &thread, int signo) :
Greg Clayton65611552011-06-04 01:26:29 +0000591 StopInfo (thread, signo)
Greg Clayton643ee732010-08-04 01:40:35 +0000592 {
593 }
594
595 virtual ~StopInfoUnixSignal ()
596 {
597 }
598
599
600 virtual StopReason
601 GetStopReason () const
602 {
603 return eStopReasonSignal;
604 }
605
606 virtual bool
607 ShouldStop (Event *event_ptr)
608 {
609 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value);
610 }
611
612
613 // If should stop returns false, check if we should notify of this event
614 virtual bool
615 ShouldNotify (Event *event_ptr)
616 {
617 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value);
618 }
619
620
621 virtual void
622 WillResume (lldb::StateType resume_state)
623 {
624 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false)
625 m_thread.SetResumeSignal(m_value);
626 }
627
628 virtual const char *
629 GetDescription ()
630 {
631 if (m_description.empty())
632 {
633 StreamString strm;
634 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value);
635 if (signal_name)
Greg Claytona830adb2010-10-04 01:05:56 +0000636 strm.Printf("signal %s", signal_name);
Greg Clayton643ee732010-08-04 01:40:35 +0000637 else
Greg Claytona830adb2010-10-04 01:05:56 +0000638 strm.Printf("signal %lli", m_value);
Greg Clayton643ee732010-08-04 01:40:35 +0000639 m_description.swap (strm.GetString());
640 }
641 return m_description.c_str();
642 }
Greg Clayton643ee732010-08-04 01:40:35 +0000643};
644
645//----------------------------------------------------------------------
646// StopInfoTrace
647//----------------------------------------------------------------------
648
649class StopInfoTrace : public StopInfo
650{
651public:
652
653 StopInfoTrace (Thread &thread) :
654 StopInfo (thread, LLDB_INVALID_UID)
655 {
656 }
657
658 virtual ~StopInfoTrace ()
659 {
660 }
661
662 virtual StopReason
663 GetStopReason () const
664 {
665 return eStopReasonTrace;
666 }
667
668 virtual const char *
669 GetDescription ()
670 {
Greg Clayton65611552011-06-04 01:26:29 +0000671 if (m_description.empty())
Greg Clayton643ee732010-08-04 01:40:35 +0000672 return "trace";
Greg Clayton65611552011-06-04 01:26:29 +0000673 else
674 return m_description.c_str();
675 }
676};
677
678
679//----------------------------------------------------------------------
680// StopInfoException
681//----------------------------------------------------------------------
682
683class StopInfoException : public StopInfo
684{
685public:
686
687 StopInfoException (Thread &thread, const char *description) :
688 StopInfo (thread, LLDB_INVALID_UID)
689 {
690 if (description)
691 SetDescription (description);
692 }
693
694 virtual
695 ~StopInfoException ()
696 {
697 }
698
699 virtual StopReason
700 GetStopReason () const
701 {
702 return eStopReasonException;
703 }
704
705 virtual const char *
706 GetDescription ()
707 {
708 if (m_description.empty())
709 return "exception";
710 else
711 return m_description.c_str();
Greg Clayton643ee732010-08-04 01:40:35 +0000712 }
713};
714
715
716//----------------------------------------------------------------------
717// StopInfoThreadPlan
718//----------------------------------------------------------------------
719
720class StopInfoThreadPlan : public StopInfo
721{
722public:
723
724 StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
725 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
726 m_plan_sp (plan_sp)
727 {
728 }
729
730 virtual ~StopInfoThreadPlan ()
731 {
732 }
733
734 virtual StopReason
735 GetStopReason () const
736 {
737 return eStopReasonPlanComplete;
738 }
739
740 virtual const char *
741 GetDescription ()
742 {
743 if (m_description.empty())
744 {
745 StreamString strm;
746 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
747 m_description.swap (strm.GetString());
748 }
749 return m_description.c_str();
750 }
751
752private:
753 ThreadPlanSP m_plan_sp;
Greg Clayton643ee732010-08-04 01:40:35 +0000754};
Jim Ingham21f37ad2011-08-09 02:12:22 +0000755} // namespace lldb_private
Greg Clayton643ee732010-08-04 01:40:35 +0000756
757StopInfoSP
758StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
759{
760 return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
761}
762
763StopInfoSP
Jim Inghamd1686902010-10-14 23:45:03 +0000764StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
765{
766 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
767}
768
769StopInfoSP
Greg Clayton643ee732010-08-04 01:40:35 +0000770StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
771{
772 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
773}
774
775StopInfoSP
776StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo)
777{
778 return StopInfoSP (new StopInfoUnixSignal (thread, signo));
779}
780
781StopInfoSP
782StopInfo::CreateStopReasonToTrace (Thread &thread)
783{
784 return StopInfoSP (new StopInfoTrace (thread));
785}
786
787StopInfoSP
788StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
789{
790 return StopInfoSP (new StopInfoThreadPlan (plan_sp));
791}
Greg Clayton65611552011-06-04 01:26:29 +0000792
793StopInfoSP
794StopInfo::CreateStopReasonWithException (Thread &thread, const char *description)
795{
796 return StopInfoSP (new StopInfoException (thread, description));
797}