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 const BreakpointOptions *
258 BreakpointLocation::GetOptionsNoCreate () const
259 {
260     if (m_options_ap.get() != NULL)
261         return m_options_ap.get();
262     else
263         return m_owner.GetOptions ();
264 }
265 
266 BreakpointOptions *
267 BreakpointLocation::GetLocationOptions ()
268 {
269     // If we make the copy we don't copy the callbacks because that is potentially
270     // expensive and we don't want to do that for the simple case where someone is
271     // just disabling the location.
272     if (m_options_ap.get() == NULL)
273         m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
274 
275     return m_options_ap.get();
276 }
277 
278 bool
279 BreakpointLocation::ValidForThisThread (Thread *thread)
280 {
281     return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
282 }
283 
284 // RETURNS - true if we should stop at this breakpoint, false if we
285 // should continue.  Note, we don't check the thread spec for the breakpoint
286 // here, since if the breakpoint is not for this thread, then the event won't
287 // even get reported, so the check is redundant.
288 
289 bool
290 BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
291 {
292     bool should_stop = true;
293     LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
294 
295     IncrementHitCount();
296 
297     if (!IsEnabled())
298         return false;
299 
300     if (GetHitCount() <= GetIgnoreCount())
301         return false;
302 
303     // We only run synchronous callbacks in ShouldStop:
304     context->is_synchronous = true;
305     should_stop = InvokeCallback (context);
306 
307     if (log)
308     {
309         StreamString s;
310         GetDescription (&s, lldb::eDescriptionLevelVerbose);
311         log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
312     }
313 
314     return should_stop;
315 }
316 
317 bool
318 BreakpointLocation::IsResolved () const
319 {
320     return m_bp_site_sp.get() != NULL;
321 }
322 
323 lldb::BreakpointSiteSP
324 BreakpointLocation::GetBreakpointSite() const
325 {
326     return m_bp_site_sp;
327 }
328 
329 bool
330 BreakpointLocation::ResolveBreakpointSite ()
331 {
332     if (m_bp_site_sp)
333         return true;
334 
335     Process *process = m_owner.GetTarget().GetProcessSP().get();
336     if (process == NULL)
337         return false;
338 
339     if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
340         return false;
341 
342     lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
343 
344     if (new_id == LLDB_INVALID_BREAK_ID)
345     {
346         LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
347         if (log)
348             log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
349                           m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
350         return false;
351     }
352 
353     return true;
354 }
355 
356 bool
357 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
358 {
359     m_bp_site_sp = bp_site_sp;
360     return true;
361 }
362 
363 bool
364 BreakpointLocation::ClearBreakpointSite ()
365 {
366     if (m_bp_site_sp.get())
367     {
368         m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
369                                                                            GetID(), m_bp_site_sp);
370         m_bp_site_sp.reset();
371         return true;
372     }
373     return false;
374 }
375 
376 void
377 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
378 {
379     SymbolContext sc;
380     s->Indent();
381     BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
382 
383     if (level == lldb::eDescriptionLevelBrief)
384         return;
385 
386     s->PutCString(": ");
387 
388     if (level == lldb::eDescriptionLevelVerbose)
389         s->IndentMore();
390 
391     if (m_address.IsSectionOffset())
392     {
393         m_address.CalculateSymbolContext(&sc);
394 
395         if (level == lldb::eDescriptionLevelFull)
396         {
397             s->PutCString("where = ");
398             sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
399         }
400         else
401         {
402             if (sc.module_sp)
403             {
404                 s->EOL();
405                 s->Indent("module = ");
406                 sc.module_sp->GetFileSpec().Dump (s);
407             }
408 
409             if (sc.comp_unit != NULL)
410             {
411                 s->EOL();
412                 s->Indent("compile unit = ");
413                 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
414 
415                 if (sc.function != NULL)
416                 {
417                     s->EOL();
418                     s->Indent("function = ");
419                     s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
420                 }
421 
422                 if (sc.line_entry.line > 0)
423                 {
424                     s->EOL();
425                     s->Indent("location = ");
426                     sc.line_entry.DumpStopContext (s, true);
427                 }
428 
429             }
430             else
431             {
432                 // If we don't have a comp unit, see if we have a symbol we can print.
433                 if (sc.symbol)
434                 {
435                     s->EOL();
436                     s->Indent("symbol = ");
437                     s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
438                 }
439             }
440         }
441     }
442 
443     if (level == lldb::eDescriptionLevelVerbose)
444     {
445         s->EOL();
446         s->Indent();
447     }
448     s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
449     ExecutionContextScope *exe_scope = NULL;
450     Target *target = &m_owner.GetTarget();
451     if (target)
452         exe_scope = target->GetProcessSP().get();
453     if (exe_scope == NULL)
454         exe_scope = target;
455 
456     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
457 
458     if (level == lldb::eDescriptionLevelVerbose)
459     {
460         s->EOL();
461         s->Indent();
462         s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
463 
464         s->Indent();
465         s->Printf ("hit count = %-4u\n", GetHitCount());
466 
467         if (m_options_ap.get())
468         {
469             s->Indent();
470             m_options_ap->GetDescription (s, level);
471             s->EOL();
472         }
473         s->IndentLess();
474     }
475     else
476     {
477         s->Printf(", %sresolved, hit count = %u ",
478                   (IsResolved() ? "" : "un"),
479                   GetHitCount());
480         if (m_options_ap.get())
481         {
482             m_options_ap->GetDescription (s, level);
483         }
484     }
485 }
486 
487 void
488 BreakpointLocation::Dump(Stream *s) const
489 {
490     if (s == NULL)
491         return;
492 
493     s->Printf("BreakpointLocation %u: tid = %4.4llx  load addr = 0x%8.8llx  state = %s  type = %s breakpoint  "
494               "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
495               GetID(),
496               GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
497               (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
498               (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
499               IsHardware() ? "hardware" : "software",
500               GetHardwareIndex(),
501               GetHitCount(),
502               GetOptionsNoCreate()->GetIgnoreCount());
503 }
504 
505 void
506 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
507 {
508     if (!m_being_created
509         && !m_owner.IsInternal()
510         && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
511     {
512         Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
513                                                                                      m_owner.shared_from_this());
514         data->GetBreakpointLocationCollection().Add (shared_from_this());
515         m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
516     }
517 }
518 
519