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