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