1 //===-- 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/Breakpoint.h"
20 #include "lldb/Breakpoint/BreakpointLocation.h"
21 #include "lldb/Breakpoint/StoppointCallbackContext.h"
22 #include "lldb/Breakpoint/WatchpointLocation.h"
23 #include "lldb/Core/Debugger.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Expression/ClangUserExpression.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28 #include "lldb/Target/ThreadPlan.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/UnixSignals.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 StopInfo::StopInfo (Thread &thread, uint64_t value) :
36     m_thread (thread),
37     m_stop_id (thread.GetProcess().GetStopID()),
38     m_value (value)
39 {
40 }
41 
42 bool
43 StopInfo::IsValid () const
44 {
45     return m_thread.GetProcess().GetStopID() == m_stop_id;
46 }
47 
48 void
49 StopInfo::MakeStopInfoValid ()
50 {
51     m_stop_id = m_thread.GetProcess().GetStopID();
52 }
53 
54 lldb::StateType
55 StopInfo::GetPrivateState ()
56 {
57     return m_thread.GetProcess().GetPrivateState();
58 }
59 
60 //----------------------------------------------------------------------
61 // StopInfoBreakpoint
62 //----------------------------------------------------------------------
63 
64 namespace lldb_private
65 {
66 class StopInfoBreakpoint : public StopInfo
67 {
68 public:
69 
70     StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
71         StopInfo (thread, break_id),
72         m_description(),
73         m_should_stop (false),
74         m_should_stop_is_valid (false),
75         m_should_perform_action (true)
76     {
77     }
78 
79     StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
80         StopInfo (thread, break_id),
81         m_description(),
82         m_should_stop (should_stop),
83         m_should_stop_is_valid (true),
84         m_should_perform_action (true)
85     {
86     }
87 
88     virtual ~StopInfoBreakpoint ()
89     {
90     }
91 
92     virtual StopReason
93     GetStopReason () const
94     {
95         return eStopReasonBreakpoint;
96     }
97 
98     virtual bool
99     ShouldStop (Event *event_ptr)
100     {
101         if (!m_should_stop_is_valid)
102         {
103             // Only check once if we should stop at a breakpoint
104             BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
105             if (bp_site_sp)
106             {
107                 StoppointCallbackContext context (event_ptr,
108                                                   &m_thread.GetProcess(),
109                                                   &m_thread,
110                                                   m_thread.GetStackFrameAtIndex(0).get(),
111                                                   true);
112 
113                 m_should_stop = bp_site_sp->ShouldStop (&context);
114             }
115             else
116             {
117                 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
118 
119                 if (log)
120                     log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
121 
122                 m_should_stop = true;
123             }
124             m_should_stop_is_valid = true;
125         }
126         return m_should_stop;
127     }
128 
129     virtual void
130     PerformAction (Event *event_ptr)
131     {
132         if (!m_should_perform_action)
133             return;
134         m_should_perform_action = false;
135 
136         LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
137         // We're going to calculate whether we should stop or not in some way during the course of
138         // this code.  So set the valid flag here.  Also by default we're going to stop, so
139         // set that here too.
140         // m_should_stop_is_valid = true;
141         m_should_stop = true;
142 
143         BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
144         if (bp_site_sp)
145         {
146             size_t num_owners = bp_site_sp->GetNumberOfOwners();
147 
148             // We only continue from the callbacks if ALL the callbacks want us to continue.
149             // However we want to run all the callbacks, except of course if one of them actually
150             // resumes the target.
151             // So we use stop_requested to track what we're were asked to do.
152             bool stop_requested = true;
153             for (size_t j = 0; j < num_owners; j++)
154             {
155                 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
156                 StoppointCallbackContext context (event_ptr,
157                                                   &m_thread.GetProcess(),
158                                                   &m_thread,
159                                                   m_thread.GetStackFrameAtIndex(0).get(),
160                                                   false);
161                 stop_requested = bp_loc_sp->InvokeCallback (&context);
162                 // Also make sure that the callback hasn't continued the target.
163                 // If it did, when we'll set m_should_start to false and get out of here.
164                 if (GetPrivateState() == eStateRunning)
165                     m_should_stop = false;
166             }
167 
168             if (m_should_stop && !stop_requested)
169             {
170                 m_should_stop_is_valid = true;
171                 m_should_stop = false;
172             }
173 
174             // Okay, so now if all the callbacks say we should stop, let's try the Conditions:
175             if (m_should_stop)
176             {
177                 size_t num_owners = bp_site_sp->GetNumberOfOwners();
178                 for (size_t j = 0; j < num_owners; j++)
179                 {
180                     lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
181                     if (bp_loc_sp->GetConditionText() != NULL)
182                     {
183                         // We need to make sure the user sees any parse errors in their condition, so we'll hook the
184                         // constructor errors up to the debugger's Async I/O.
185 
186                         StoppointCallbackContext context (event_ptr,
187                                                           &m_thread.GetProcess(),
188                                                           &m_thread,
189                                                           m_thread.GetStackFrameAtIndex(0).get(),
190                                                           false);
191                         ValueObjectSP result_valobj_sp;
192 
193                         ExecutionResults result_code;
194                         ValueObjectSP result_value_sp;
195                         const bool discard_on_error = true;
196                         Error error;
197                         result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
198                                                                               eExecutionPolicyAlways,
199                                                                               discard_on_error,
200                                                                               bp_loc_sp->GetConditionText(),
201                                                                               NULL,
202                                                                               result_value_sp,
203                                                                               error);
204                         if (result_code == eExecutionCompleted)
205                         {
206                             if (result_value_sp)
207                             {
208                                 Scalar scalar_value;
209                                 if (result_value_sp->ResolveValue (scalar_value))
210                                 {
211                                     if (scalar_value.ULongLong(1) == 0)
212                                         m_should_stop = false;
213                                     else
214                                         m_should_stop = true;
215                                     if (log)
216                                         log->Printf("Condition successfully evaluated, result is %s.\n",
217                                                     m_should_stop ? "true" : "false");
218                                 }
219                                 else
220                                 {
221                                     m_should_stop = true;
222                                     if (log)
223                                         log->Printf("Failed to get an integer result from the expression.");
224                                 }
225                             }
226                         }
227                         else
228                         {
229                             Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger();
230                             StreamSP error_sp = debugger.GetAsyncErrorStream ();
231                             error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
232                             bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
233                             error_sp->Printf (": \"%s\"",
234                                               bp_loc_sp->GetConditionText());
235                             error_sp->EOL();
236                             const char *err_str = error.AsCString("<Unknown Error>");
237                             if (log)
238                                 log->Printf("Error evaluating condition: \"%s\"\n", err_str);
239 
240                             error_sp->PutCString (err_str);
241                             error_sp->EOL();
242                             error_sp->Flush();
243                             // If the condition fails to be parsed or run, we should stop.
244                             m_should_stop = true;
245                         }
246                     }
247 
248                     // If any condition says we should stop, then we're going to stop, so we don't need
249                     // to evaluate the others.
250                     if (m_should_stop)
251                         break;
252                 }
253             }
254         }
255         else
256         {
257             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
258 
259             if (log)
260                 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
261         }
262         if (log)
263             log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
264     }
265 
266     virtual bool
267     ShouldNotify (Event *event_ptr)
268     {
269         BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
270         if (bp_site_sp)
271         {
272             bool all_internal = true;
273 
274             for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
275             {
276                 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
277                 {
278                     all_internal = false;
279                     break;
280                 }
281             }
282             return all_internal == false;
283         }
284         return true;
285     }
286 
287     virtual const char *
288     GetDescription ()
289     {
290         if (m_description.empty())
291         {
292             BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
293             if (bp_site_sp)
294             {
295                 StreamString strm;
296                 strm.Printf("breakpoint ");
297                 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
298                 m_description.swap (strm.GetString());
299             }
300             else
301             {
302                 StreamString strm;
303                 strm.Printf("breakpoint site %lli", m_value);
304                 m_description.swap (strm.GetString());
305             }
306         }
307         return m_description.c_str();
308     }
309 
310 private:
311     std::string m_description;
312     bool m_should_stop;
313     bool m_should_stop_is_valid;
314     bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions
315                                   // etc. behind the users backs, we need to make sure we only REALLY perform the action once.
316 };
317 
318 
319 //----------------------------------------------------------------------
320 // StopInfoWatchpoint
321 //----------------------------------------------------------------------
322 
323 class StopInfoWatchpoint : public StopInfo
324 {
325 public:
326 
327     StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
328         StopInfo(thread, watch_id),
329         m_description(),
330         m_should_stop(false),
331         m_should_stop_is_valid(false)
332     {
333     }
334 
335     virtual ~StopInfoWatchpoint ()
336     {
337     }
338 
339     virtual StopReason
340     GetStopReason () const
341     {
342         return eStopReasonWatchpoint;
343     }
344 
345     virtual bool
346     ShouldStop (Event *event_ptr)
347     {
348         // ShouldStop() method is idempotent and should not affect hit count.
349         if (m_should_stop_is_valid)
350             return m_should_stop;
351 
352         WatchpointLocationSP wp_loc_sp =
353             m_thread.GetProcess().GetTarget().GetWatchpointLocationList().FindByID(GetValue());
354         if (wp_loc_sp)
355         {
356             // Check if we should stop at a watchpoint.
357             StoppointCallbackContext context (event_ptr,
358                                               &m_thread.GetProcess(),
359                                               &m_thread,
360                                               m_thread.GetStackFrameAtIndex(0).get(),
361                                               true);
362 
363             m_should_stop = wp_loc_sp->ShouldStop (&context);
364         }
365         else
366         {
367             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
368 
369             if (log)
370                 log->Printf ("Process::%s could not find watchpoint location id: %lld...",
371                              __FUNCTION__, GetValue());
372 
373             m_should_stop = true;
374         }
375         m_should_stop_is_valid = true;
376         return m_should_stop;
377     }
378 
379     virtual const char *
380     GetDescription ()
381     {
382         if (m_description.empty())
383         {
384             StreamString strm;
385             strm.Printf("watchpoint %lli", m_value);
386             m_description.swap (strm.GetString());
387         }
388         return m_description.c_str();
389     }
390 
391 private:
392     std::string m_description;
393     bool m_should_stop;
394     bool m_should_stop_is_valid;
395 };
396 
397 
398 
399 //----------------------------------------------------------------------
400 // StopInfoUnixSignal
401 //----------------------------------------------------------------------
402 
403 class StopInfoUnixSignal : public StopInfo
404 {
405 public:
406 
407     StopInfoUnixSignal (Thread &thread, int signo) :
408         StopInfo (thread, signo)
409     {
410     }
411 
412     virtual ~StopInfoUnixSignal ()
413     {
414     }
415 
416 
417     virtual StopReason
418     GetStopReason () const
419     {
420         return eStopReasonSignal;
421     }
422 
423     virtual bool
424     ShouldStop (Event *event_ptr)
425     {
426         return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value);
427     }
428 
429 
430     // If should stop returns false, check if we should notify of this event
431     virtual bool
432     ShouldNotify (Event *event_ptr)
433     {
434         return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value);
435     }
436 
437 
438     virtual void
439     WillResume (lldb::StateType resume_state)
440     {
441         if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false)
442             m_thread.SetResumeSignal(m_value);
443     }
444 
445     virtual const char *
446     GetDescription ()
447     {
448         if (m_description.empty())
449         {
450             StreamString strm;
451             const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value);
452             if (signal_name)
453                 strm.Printf("signal %s", signal_name);
454             else
455                 strm.Printf("signal %lli", m_value);
456             m_description.swap (strm.GetString());
457         }
458         return m_description.c_str();
459     }
460 };
461 
462 //----------------------------------------------------------------------
463 // StopInfoTrace
464 //----------------------------------------------------------------------
465 
466 class StopInfoTrace : public StopInfo
467 {
468 public:
469 
470     StopInfoTrace (Thread &thread) :
471         StopInfo (thread, LLDB_INVALID_UID)
472     {
473     }
474 
475     virtual ~StopInfoTrace ()
476     {
477     }
478 
479     virtual StopReason
480     GetStopReason () const
481     {
482         return eStopReasonTrace;
483     }
484 
485     virtual const char *
486     GetDescription ()
487     {
488         if (m_description.empty())
489         return "trace";
490         else
491             return m_description.c_str();
492     }
493 };
494 
495 
496 //----------------------------------------------------------------------
497 // StopInfoException
498 //----------------------------------------------------------------------
499 
500 class StopInfoException : public StopInfo
501 {
502 public:
503 
504     StopInfoException (Thread &thread, const char *description) :
505         StopInfo (thread, LLDB_INVALID_UID)
506     {
507         if (description)
508             SetDescription (description);
509     }
510 
511     virtual
512     ~StopInfoException ()
513     {
514     }
515 
516     virtual StopReason
517     GetStopReason () const
518     {
519         return eStopReasonException;
520     }
521 
522     virtual const char *
523     GetDescription ()
524     {
525         if (m_description.empty())
526             return "exception";
527         else
528             return m_description.c_str();
529     }
530 };
531 
532 
533 //----------------------------------------------------------------------
534 // StopInfoThreadPlan
535 //----------------------------------------------------------------------
536 
537 class StopInfoThreadPlan : public StopInfo
538 {
539 public:
540 
541     StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
542         StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
543         m_plan_sp (plan_sp)
544     {
545     }
546 
547     virtual ~StopInfoThreadPlan ()
548     {
549     }
550 
551     virtual StopReason
552     GetStopReason () const
553     {
554         return eStopReasonPlanComplete;
555     }
556 
557     virtual const char *
558     GetDescription ()
559     {
560         if (m_description.empty())
561         {
562             StreamString strm;
563             m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
564             m_description.swap (strm.GetString());
565         }
566         return m_description.c_str();
567     }
568 
569 private:
570     ThreadPlanSP m_plan_sp;
571 };
572 } // namespace lldb_private
573 
574 StopInfoSP
575 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
576 {
577     return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
578 }
579 
580 StopInfoSP
581 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
582 {
583     return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
584 }
585 
586 StopInfoSP
587 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
588 {
589     return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
590 }
591 
592 StopInfoSP
593 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo)
594 {
595     return StopInfoSP (new StopInfoUnixSignal (thread, signo));
596 }
597 
598 StopInfoSP
599 StopInfo::CreateStopReasonToTrace (Thread &thread)
600 {
601     return StopInfoSP (new StopInfoTrace (thread));
602 }
603 
604 StopInfoSP
605 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
606 {
607     return StopInfoSP (new StopInfoThreadPlan (plan_sp));
608 }
609 
610 StopInfoSP
611 StopInfo::CreateStopReasonWithException (Thread &thread, const char *description)
612 {
613     return StopInfoSP (new StopInfoException (thread, description));
614 }
615