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