• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- BreakpointLocation.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/lldb-python.h"
11 
12 // C Includes
13 // C++ Includes
14 #include <string>
15 
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-private-log.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/BreakpointID.h"
21 #include "lldb/Breakpoint/StoppointCallbackContext.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/StreamString.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/Symbol.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/Thread.h"
31 #include "lldb/Target/ThreadSpec.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
BreakpointLocation(break_id_t loc_id,Breakpoint & owner,const Address & addr,lldb::tid_t tid,bool hardware)36 BreakpointLocation::BreakpointLocation
37 (
38     break_id_t loc_id,
39     Breakpoint &owner,
40     const Address &addr,
41     lldb::tid_t tid,
42     bool hardware
43 ) :
44     StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
45     m_being_created(true),
46     m_address (addr),
47     m_owner (owner),
48     m_options_ap (),
49     m_bp_site_sp (),
50     m_condition_mutex ()
51 {
52     SetThreadID (tid);
53     m_being_created = false;
54 }
55 
~BreakpointLocation()56 BreakpointLocation::~BreakpointLocation()
57 {
58     ClearBreakpointSite();
59 }
60 
61 lldb::addr_t
GetLoadAddress() const62 BreakpointLocation::GetLoadAddress () const
63 {
64     return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
65 }
66 
67 Address &
GetAddress()68 BreakpointLocation::GetAddress ()
69 {
70     return m_address;
71 }
72 
73 Breakpoint &
GetBreakpoint()74 BreakpointLocation::GetBreakpoint ()
75 {
76     return m_owner;
77 }
78 
79 bool
IsEnabled() const80 BreakpointLocation::IsEnabled () const
81 {
82     if (!m_owner.IsEnabled())
83         return false;
84     else if (m_options_ap.get() != NULL)
85         return m_options_ap->IsEnabled();
86     else
87         return true;
88 }
89 
90 void
SetEnabled(bool enabled)91 BreakpointLocation::SetEnabled (bool enabled)
92 {
93     GetLocationOptions()->SetEnabled(enabled);
94     if (enabled)
95     {
96         ResolveBreakpointSite();
97     }
98     else
99     {
100         ClearBreakpointSite();
101     }
102     SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
103 }
104 
105 void
SetThreadID(lldb::tid_t thread_id)106 BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
107 {
108     if (thread_id != LLDB_INVALID_THREAD_ID)
109         GetLocationOptions()->SetThreadID(thread_id);
110     else
111     {
112         // If we're resetting this to an invalid thread id, then
113         // don't make an options pointer just to do that.
114         if (m_options_ap.get() != NULL)
115             m_options_ap->SetThreadID (thread_id);
116     }
117     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
118 }
119 
120 lldb::tid_t
GetThreadID()121 BreakpointLocation::GetThreadID ()
122 {
123     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
124         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
125     else
126         return LLDB_INVALID_THREAD_ID;
127 }
128 
129 void
SetThreadIndex(uint32_t index)130 BreakpointLocation::SetThreadIndex (uint32_t index)
131 {
132     if (index != 0)
133         GetLocationOptions()->GetThreadSpec()->SetIndex(index);
134     else
135     {
136         // If we're resetting this to an invalid thread id, then
137         // don't make an options pointer just to do that.
138         if (m_options_ap.get() != NULL)
139             m_options_ap->GetThreadSpec()->SetIndex(index);
140     }
141     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
142 
143 }
144 
145 uint32_t
GetThreadIndex() const146 BreakpointLocation::GetThreadIndex() const
147 {
148     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
149         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
150     else
151         return 0;
152 }
153 
154 void
SetThreadName(const char * thread_name)155 BreakpointLocation::SetThreadName (const char *thread_name)
156 {
157     if (thread_name != NULL)
158         GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
159     else
160     {
161         // If we're resetting this to an invalid thread id, then
162         // don't make an options pointer just to do that.
163         if (m_options_ap.get() != NULL)
164             m_options_ap->GetThreadSpec()->SetName(thread_name);
165     }
166     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
167 }
168 
169 const char *
GetThreadName() const170 BreakpointLocation::GetThreadName () const
171 {
172     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
173         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
174     else
175         return NULL;
176 }
177 
178 void
SetQueueName(const char * queue_name)179 BreakpointLocation::SetQueueName (const char *queue_name)
180 {
181     if (queue_name != NULL)
182         GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
183     else
184     {
185         // If we're resetting this to an invalid thread id, then
186         // don't make an options pointer just to do that.
187         if (m_options_ap.get() != NULL)
188             m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
189     }
190     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
191 }
192 
193 const char *
GetQueueName() const194 BreakpointLocation::GetQueueName () const
195 {
196     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
197         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
198     else
199         return NULL;
200 }
201 
202 bool
InvokeCallback(StoppointCallbackContext * context)203 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
204 {
205     if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
206         return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
207     else
208         return m_owner.InvokeCallback (context, GetID());
209 }
210 
211 void
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)212 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
213                  bool is_synchronous)
214 {
215     // The default "Baton" class will keep a copy of "baton" and won't free
216     // or delete it when it goes goes out of scope.
217     GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
218     SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
219 }
220 
221 void
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)222 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
223                  bool is_synchronous)
224 {
225     GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
226     SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
227 }
228 
229 
230 void
ClearCallback()231 BreakpointLocation::ClearCallback ()
232 {
233     GetLocationOptions()->ClearCallback();
234 }
235 
236 void
SetCondition(const char * condition)237 BreakpointLocation::SetCondition (const char *condition)
238 {
239     GetLocationOptions()->SetCondition (condition);
240     SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged);
241 }
242 
243 const char *
GetConditionText(size_t * hash) const244 BreakpointLocation::GetConditionText (size_t *hash) const
245 {
246     return GetOptionsNoCreate()->GetConditionText(hash);
247 }
248 
249 bool
ConditionSaysStop(ExecutionContext & exe_ctx,Error & error)250 BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
251 {
252     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
253 
254     Mutex::Locker evaluation_locker(m_condition_mutex);
255 
256     size_t condition_hash;
257     const char *condition_text = GetConditionText(&condition_hash);
258 
259     if (!condition_text)
260     {
261         m_user_expression_sp.reset();
262         return false;
263     }
264 
265     if (condition_hash != m_condition_hash ||
266         !m_user_expression_sp ||
267         !m_user_expression_sp->MatchesContext(exe_ctx))
268     {
269         m_user_expression_sp.reset(new ClangUserExpression(condition_text,
270                                                            NULL,
271                                                            lldb::eLanguageTypeUnknown,
272                                                            ClangUserExpression::eResultTypeAny));
273 
274         StreamString errors;
275 
276         if (!m_user_expression_sp->Parse(errors,
277                                          exe_ctx,
278                                          eExecutionPolicyOnlyWhenNeeded,
279                                          true))
280         {
281             error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
282                                            errors.GetData());
283             m_user_expression_sp.reset();
284             return false;
285         }
286 
287         m_condition_hash = condition_hash;
288     }
289 
290     // We need to make sure the user sees any parse errors in their condition, so we'll hook the
291     // constructor errors up to the debugger's Async I/O.
292 
293     ValueObjectSP result_value_sp;
294     const bool unwind_on_error = true;
295     const bool ignore_breakpoints = true;
296     const bool try_all_threads = true;
297 
298     Error expr_error;
299 
300     StreamString execution_errors;
301 
302     ClangExpressionVariableSP result_variable_sp;
303 
304     ExecutionResults result_code =
305     m_user_expression_sp->Execute(execution_errors,
306                                   exe_ctx,
307                                   unwind_on_error,
308                                   ignore_breakpoints,
309                                   m_user_expression_sp,
310                                   result_variable_sp,
311                                   try_all_threads,
312                                   ClangUserExpression::kDefaultTimeout);
313 
314     bool ret;
315 
316     if (result_code == eExecutionCompleted)
317     {
318         if (!result_variable_sp)
319         {
320             ret = false;
321             error.SetErrorString("Expression did not return a result");
322             return false;
323         }
324 
325         result_value_sp = result_variable_sp->GetValueObject();
326 
327         if (result_value_sp)
328         {
329             Scalar scalar_value;
330             if (result_value_sp->ResolveValue (scalar_value))
331             {
332                 if (scalar_value.ULongLong(1) == 0)
333                     ret = false;
334                 else
335                     ret = true;
336                 if (log)
337                     log->Printf("Condition successfully evaluated, result is %s.\n",
338                                 ret ? "true" : "false");
339             }
340             else
341             {
342                 ret = false;
343                 error.SetErrorString("Failed to get an integer result from the expression");
344             }
345         }
346         else
347         {
348             ret = false;
349             error.SetErrorString("Failed to get any result from the expression");
350         }
351     }
352     else
353     {
354         ret = false;
355         error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData());
356     }
357 
358     return ret;
359 }
360 
361 uint32_t
GetIgnoreCount()362 BreakpointLocation::GetIgnoreCount ()
363 {
364     return GetOptionsNoCreate()->GetIgnoreCount();
365 }
366 
367 void
SetIgnoreCount(uint32_t n)368 BreakpointLocation::SetIgnoreCount (uint32_t n)
369 {
370     GetLocationOptions()->SetIgnoreCount(n);
371     SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged);
372 }
373 
374 void
DecrementIgnoreCount()375 BreakpointLocation::DecrementIgnoreCount()
376 {
377     if (m_options_ap.get() != NULL)
378     {
379         uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
380         if (loc_ignore != 0)
381             m_options_ap->SetIgnoreCount(loc_ignore - 1);
382     }
383 }
384 
385 bool
IgnoreCountShouldStop()386 BreakpointLocation::IgnoreCountShouldStop()
387 {
388     if (m_options_ap.get() != NULL)
389     {
390         uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
391         if (loc_ignore != 0)
392         {
393             m_owner.DecrementIgnoreCount();
394             DecrementIgnoreCount();          // Have to decrement our owners' ignore count, since it won't get a
395                                              // chance to.
396             return false;
397         }
398     }
399     return true;
400 }
401 
402 const BreakpointOptions *
GetOptionsNoCreate() const403 BreakpointLocation::GetOptionsNoCreate () const
404 {
405     if (m_options_ap.get() != NULL)
406         return m_options_ap.get();
407     else
408         return m_owner.GetOptions ();
409 }
410 
411 BreakpointOptions *
GetLocationOptions()412 BreakpointLocation::GetLocationOptions ()
413 {
414     // If we make the copy we don't copy the callbacks because that is potentially
415     // expensive and we don't want to do that for the simple case where someone is
416     // just disabling the location.
417     if (m_options_ap.get() == NULL)
418         m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
419 
420     return m_options_ap.get();
421 }
422 
423 bool
ValidForThisThread(Thread * thread)424 BreakpointLocation::ValidForThisThread (Thread *thread)
425 {
426     return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
427 }
428 
429 // RETURNS - true if we should stop at this breakpoint, false if we
430 // should continue.  Note, we don't check the thread spec for the breakpoint
431 // here, since if the breakpoint is not for this thread, then the event won't
432 // even get reported, so the check is redundant.
433 
434 bool
ShouldStop(StoppointCallbackContext * context)435 BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
436 {
437     bool should_stop = true;
438     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
439 
440     IncrementHitCount();
441 
442     if (!IsEnabled())
443         return false;
444 
445     if (!IgnoreCountShouldStop())
446         return false;
447 
448     if (!m_owner.IgnoreCountShouldStop())
449         return false;
450 
451     // We only run synchronous callbacks in ShouldStop:
452     context->is_synchronous = true;
453     should_stop = InvokeCallback (context);
454 
455     if (log)
456     {
457         StreamString s;
458         GetDescription (&s, lldb::eDescriptionLevelVerbose);
459         log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
460     }
461 
462     return should_stop;
463 }
464 
465 bool
IsResolved() const466 BreakpointLocation::IsResolved () const
467 {
468     return m_bp_site_sp.get() != NULL;
469 }
470 
471 lldb::BreakpointSiteSP
GetBreakpointSite() const472 BreakpointLocation::GetBreakpointSite() const
473 {
474     return m_bp_site_sp;
475 }
476 
477 bool
ResolveBreakpointSite()478 BreakpointLocation::ResolveBreakpointSite ()
479 {
480     if (m_bp_site_sp)
481         return true;
482 
483     Process *process = m_owner.GetTarget().GetProcessSP().get();
484     if (process == NULL)
485         return false;
486 
487     lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
488 
489     if (new_id == LLDB_INVALID_BREAK_ID)
490     {
491         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
492         if (log)
493             log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n",
494                           m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
495         return false;
496     }
497 
498     return true;
499 }
500 
501 bool
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)502 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
503 {
504     m_bp_site_sp = bp_site_sp;
505     return true;
506 }
507 
508 bool
ClearBreakpointSite()509 BreakpointLocation::ClearBreakpointSite ()
510 {
511     if (m_bp_site_sp.get())
512     {
513         m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
514                                                                            GetID(), m_bp_site_sp);
515         m_bp_site_sp.reset();
516         return true;
517     }
518     return false;
519 }
520 
521 void
GetDescription(Stream * s,lldb::DescriptionLevel level)522 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
523 {
524     SymbolContext sc;
525 
526     // If the description level is "initial" then the breakpoint is printing out our initial state,
527     // and we should let it decide how it wants to print our label.
528     if (level != eDescriptionLevelInitial)
529     {
530         s->Indent();
531         BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
532     }
533 
534     if (level == lldb::eDescriptionLevelBrief)
535         return;
536 
537     if (level != eDescriptionLevelInitial)
538         s->PutCString(": ");
539 
540     if (level == lldb::eDescriptionLevelVerbose)
541         s->IndentMore();
542 
543     if (m_address.IsSectionOffset())
544     {
545         m_address.CalculateSymbolContext(&sc);
546 
547         if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
548         {
549             s->PutCString("where = ");
550             sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
551         }
552         else
553         {
554             if (sc.module_sp)
555             {
556                 s->EOL();
557                 s->Indent("module = ");
558                 sc.module_sp->GetFileSpec().Dump (s);
559             }
560 
561             if (sc.comp_unit != NULL)
562             {
563                 s->EOL();
564                 s->Indent("compile unit = ");
565                 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
566 
567                 if (sc.function != NULL)
568                 {
569                     s->EOL();
570                     s->Indent("function = ");
571                     s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
572                 }
573 
574                 if (sc.line_entry.line > 0)
575                 {
576                     s->EOL();
577                     s->Indent("location = ");
578                     sc.line_entry.DumpStopContext (s, true);
579                 }
580 
581             }
582             else
583             {
584                 // If we don't have a comp unit, see if we have a symbol we can print.
585                 if (sc.symbol)
586                 {
587                     s->EOL();
588                     s->Indent("symbol = ");
589                     s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
590                 }
591             }
592         }
593     }
594 
595     if (level == lldb::eDescriptionLevelVerbose)
596     {
597         s->EOL();
598         s->Indent();
599     }
600 
601     if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
602         s->Printf (", ");
603     s->Printf ("address = ");
604 
605     ExecutionContextScope *exe_scope = NULL;
606     Target *target = &m_owner.GetTarget();
607     if (target)
608         exe_scope = target->GetProcessSP().get();
609     if (exe_scope == NULL)
610         exe_scope = target;
611 
612     if (eDescriptionLevelInitial)
613         m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
614     else
615         m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
616 
617     if (level == lldb::eDescriptionLevelVerbose)
618     {
619         s->EOL();
620         s->Indent();
621         s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
622 
623         s->Indent();
624         s->Printf ("hit count = %-4u\n", GetHitCount());
625 
626         if (m_options_ap.get())
627         {
628             s->Indent();
629             m_options_ap->GetDescription (s, level);
630             s->EOL();
631         }
632         s->IndentLess();
633     }
634     else if (level != eDescriptionLevelInitial)
635     {
636         s->Printf(", %sresolved, hit count = %u ",
637                   (IsResolved() ? "" : "un"),
638                   GetHitCount());
639         if (m_options_ap.get())
640         {
641             m_options_ap->GetDescription (s, level);
642         }
643     }
644 }
645 
646 void
Dump(Stream * s) const647 BreakpointLocation::Dump(Stream *s) const
648 {
649     if (s == NULL)
650         return;
651 
652     s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
653               "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
654               GetID(),
655               GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
656               (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
657               (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
658               IsHardware() ? "hardware" : "software",
659               GetHardwareIndex(),
660               GetHitCount(),
661               GetOptionsNoCreate()->GetIgnoreCount());
662 }
663 
664 void
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)665 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
666 {
667     if (!m_being_created
668         && !m_owner.IsInternal()
669         && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
670     {
671         Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
672                                                                                      m_owner.shared_from_this());
673         data->GetBreakpointLocationCollection().Add (shared_from_this());
674         m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
675     }
676 }
677 
678