1 //===-- SBBreakpoint.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/API/SBBreakpoint.h"
11 #include "lldb/API/SBBreakpointLocation.h"
12 #include "lldb/API/SBDebugger.h"
13 #include "lldb/API/SBEvent.h"
14 #include "lldb/API/SBProcess.h"
15 #include "lldb/API/SBStream.h"
16 #include "lldb/API/SBThread.h"
17 
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/StoppointCallbackContext.h"
21 #include "lldb/Core/Address.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Stream.h"
25 #include "lldb/Core/StreamFile.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Interpreter/ScriptInterpreter.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/SectionLoadList.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 #include "lldb/Target/ThreadSpec.h"
33 
34 
35 #include "lldb/lldb-enumerations.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 struct CallbackData
41 {
42     SBBreakpoint::BreakpointHitCallback callback;
43     void *callback_baton;
44 };
45 
46 class SBBreakpointCallbackBaton : public Baton
47 {
48 public:
49 
50     SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
51         Baton (new CallbackData)
52     {
53         CallbackData *data = (CallbackData *)m_data;
54         data->callback = callback;
55         data->callback_baton = baton;
56     }
57 
58     virtual ~SBBreakpointCallbackBaton()
59     {
60         CallbackData *data = (CallbackData *)m_data;
61 
62         if (data)
63         {
64             delete data;
65             m_data = NULL;
66         }
67     }
68 };
69 
70 
71 SBBreakpoint::SBBreakpoint () :
72     m_opaque_sp ()
73 {
74 }
75 
76 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
77     m_opaque_sp (rhs.m_opaque_sp)
78 {
79 }
80 
81 
82 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
83     m_opaque_sp (bp_sp)
84 {
85 }
86 
87 SBBreakpoint::~SBBreakpoint()
88 {
89 }
90 
91 const SBBreakpoint &
92 SBBreakpoint::operator = (const SBBreakpoint& rhs)
93 {
94     if (this != &rhs)
95         m_opaque_sp = rhs.m_opaque_sp;
96     return *this;
97 }
98 
99 bool
100 SBBreakpoint::operator == (const lldb::SBBreakpoint& rhs)
101 {
102     if (m_opaque_sp && rhs.m_opaque_sp)
103         return m_opaque_sp.get() == rhs.m_opaque_sp.get();
104     return false;
105 }
106 
107 bool
108 SBBreakpoint::operator != (const lldb::SBBreakpoint& rhs)
109 {
110     if (m_opaque_sp && rhs.m_opaque_sp)
111         return m_opaque_sp.get() != rhs.m_opaque_sp.get();
112     return (m_opaque_sp && !rhs.m_opaque_sp) || (rhs.m_opaque_sp && !m_opaque_sp);
113 }
114 
115 break_id_t
116 SBBreakpoint::GetID () const
117 {
118     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
119 
120     break_id_t break_id = LLDB_INVALID_BREAK_ID;
121     if (m_opaque_sp)
122         break_id = m_opaque_sp->GetID();
123 
124     if (log)
125     {
126         if (break_id == LLDB_INVALID_BREAK_ID)
127             log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID",
128                          static_cast<void*>(m_opaque_sp.get()));
129         else
130             log->Printf ("SBBreakpoint(%p)::GetID () => %u",
131                          static_cast<void*>(m_opaque_sp.get()), break_id);
132     }
133 
134     return break_id;
135 }
136 
137 
138 bool
139 SBBreakpoint::IsValid() const
140 {
141     return (bool) m_opaque_sp;
142 }
143 
144 void
145 SBBreakpoint::ClearAllBreakpointSites ()
146 {
147     if (m_opaque_sp)
148     {
149         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
150         m_opaque_sp->ClearAllBreakpointSites ();
151     }
152 }
153 
154 SBBreakpointLocation
155 SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
156 {
157     SBBreakpointLocation sb_bp_location;
158 
159     if (m_opaque_sp)
160     {
161         if (vm_addr != LLDB_INVALID_ADDRESS)
162         {
163             Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
164             Address address;
165             Target &target = m_opaque_sp->GetTarget();
166             if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
167             {
168                 address.SetRawAddress (vm_addr);
169             }
170             sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address));
171         }
172     }
173     return sb_bp_location;
174 }
175 
176 break_id_t
177 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
178 {
179     break_id_t break_id = LLDB_INVALID_BREAK_ID;
180 
181     if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS)
182     {
183         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
184         Address address;
185         Target &target = m_opaque_sp->GetTarget();
186         if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
187         {
188             address.SetRawAddress (vm_addr);
189         }
190         break_id = m_opaque_sp->FindLocationIDByAddress (address);
191     }
192 
193     return break_id;
194 }
195 
196 SBBreakpointLocation
197 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
198 {
199     SBBreakpointLocation sb_bp_location;
200 
201     if (m_opaque_sp)
202     {
203         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
204         sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id));
205     }
206 
207     return sb_bp_location;
208 }
209 
210 SBBreakpointLocation
211 SBBreakpoint::GetLocationAtIndex (uint32_t index)
212 {
213     SBBreakpointLocation sb_bp_location;
214 
215     if (m_opaque_sp)
216     {
217         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
218         sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index));
219     }
220 
221     return sb_bp_location;
222 }
223 
224 void
225 SBBreakpoint::SetEnabled (bool enable)
226 {
227     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
228 
229     if (log)
230         log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)",
231                      static_cast<void*>(m_opaque_sp.get()), enable);
232 
233     if (m_opaque_sp)
234     {
235         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
236         m_opaque_sp->SetEnabled (enable);
237     }
238 }
239 
240 bool
241 SBBreakpoint::IsEnabled ()
242 {
243     if (m_opaque_sp)
244     {
245         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
246         return m_opaque_sp->IsEnabled();
247     }
248     else
249         return false;
250 }
251 
252 void
253 SBBreakpoint::SetOneShot (bool one_shot)
254 {
255     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
256 
257     if (log)
258         log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)",
259                      static_cast<void*>(m_opaque_sp.get()), one_shot);
260 
261     if (m_opaque_sp)
262     {
263         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
264         m_opaque_sp->SetOneShot (one_shot);
265     }
266 }
267 
268 bool
269 SBBreakpoint::IsOneShot () const
270 {
271     if (m_opaque_sp)
272     {
273         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
274         return m_opaque_sp->IsOneShot();
275     }
276     else
277         return false;
278 }
279 
280 bool
281 SBBreakpoint::IsInternal ()
282 {
283     if (m_opaque_sp)
284     {
285         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
286         return m_opaque_sp->IsInternal();
287     }
288     else
289         return false;
290 }
291 
292 void
293 SBBreakpoint::SetIgnoreCount (uint32_t count)
294 {
295     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
296 
297     if (log)
298         log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)",
299                      static_cast<void*>(m_opaque_sp.get()), count);
300 
301     if (m_opaque_sp)
302     {
303         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
304         m_opaque_sp->SetIgnoreCount (count);
305     }
306 }
307 
308 void
309 SBBreakpoint::SetCondition (const char *condition)
310 {
311     if (m_opaque_sp)
312     {
313         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
314         m_opaque_sp->SetCondition (condition);
315     }
316 }
317 
318 const char *
319 SBBreakpoint::GetCondition ()
320 {
321     if (m_opaque_sp)
322     {
323         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
324         return m_opaque_sp->GetConditionText ();
325     }
326     return NULL;
327 }
328 
329 uint32_t
330 SBBreakpoint::GetHitCount () const
331 {
332     uint32_t count = 0;
333     if (m_opaque_sp)
334     {
335         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
336         count = m_opaque_sp->GetHitCount();
337     }
338 
339     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
340     if (log)
341         log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u",
342                      static_cast<void*>(m_opaque_sp.get()), count);
343 
344     return count;
345 }
346 
347 uint32_t
348 SBBreakpoint::GetIgnoreCount () const
349 {
350     uint32_t count = 0;
351     if (m_opaque_sp)
352     {
353         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
354         count = m_opaque_sp->GetIgnoreCount();
355     }
356 
357     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
358     if (log)
359         log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u",
360                      static_cast<void*>(m_opaque_sp.get()), count);
361 
362     return count;
363 }
364 
365 void
366 SBBreakpoint::SetThreadID (tid_t tid)
367 {
368     if (m_opaque_sp)
369     {
370         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
371         m_opaque_sp->SetThreadID (tid);
372     }
373     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
374     if (log)
375         log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")",
376                      static_cast<void*>(m_opaque_sp.get()), tid);
377 
378 }
379 
380 tid_t
381 SBBreakpoint::GetThreadID ()
382 {
383     tid_t tid = LLDB_INVALID_THREAD_ID;
384     if (m_opaque_sp)
385     {
386         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
387         tid = m_opaque_sp->GetThreadID();
388     }
389 
390     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
391     if (log)
392         log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64,
393                      static_cast<void*>(m_opaque_sp.get()), tid);
394     return tid;
395 }
396 
397 void
398 SBBreakpoint::SetThreadIndex (uint32_t index)
399 {
400     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
401     if (log)
402         log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)",
403                      static_cast<void*>(m_opaque_sp.get()), index);
404     if (m_opaque_sp)
405     {
406         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
407         m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
408     }
409 }
410 
411 uint32_t
412 SBBreakpoint::GetThreadIndex() const
413 {
414     uint32_t thread_idx = UINT32_MAX;
415     if (m_opaque_sp)
416     {
417         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
418         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
419         if (thread_spec != NULL)
420             thread_idx = thread_spec->GetIndex();
421     }
422     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
423     if (log)
424         log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u",
425                      static_cast<void*>(m_opaque_sp.get()), thread_idx);
426 
427     return thread_idx;
428 }
429 
430 void
431 SBBreakpoint::SetThreadName (const char *thread_name)
432 {
433     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
434     if (log)
435         log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)",
436                      static_cast<void*>(m_opaque_sp.get()), thread_name);
437 
438     if (m_opaque_sp)
439     {
440         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
441         m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
442     }
443 }
444 
445 const char *
446 SBBreakpoint::GetThreadName () const
447 {
448     const char *name = NULL;
449     if (m_opaque_sp)
450     {
451         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
452         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
453         if (thread_spec != NULL)
454             name = thread_spec->GetName();
455     }
456     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
457     if (log)
458         log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s",
459                      static_cast<void*>(m_opaque_sp.get()), name);
460 
461     return name;
462 }
463 
464 void
465 SBBreakpoint::SetQueueName (const char *queue_name)
466 {
467     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
468     if (log)
469         log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)",
470                      static_cast<void*>(m_opaque_sp.get()), queue_name);
471     if (m_opaque_sp)
472     {
473         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
474         m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
475     }
476 }
477 
478 const char *
479 SBBreakpoint::GetQueueName () const
480 {
481     const char *name = NULL;
482     if (m_opaque_sp)
483     {
484         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
485         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
486         if (thread_spec)
487             name = thread_spec->GetQueueName();
488     }
489     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
490     if (log)
491         log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s",
492                      static_cast<void*>(m_opaque_sp.get()), name);
493 
494     return name;
495 }
496 
497 size_t
498 SBBreakpoint::GetNumResolvedLocations() const
499 {
500     size_t num_resolved = 0;
501     if (m_opaque_sp)
502     {
503         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
504         num_resolved = m_opaque_sp->GetNumResolvedLocations();
505     }
506     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
507     if (log)
508         log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64,
509                      static_cast<void*>(m_opaque_sp.get()),
510                      static_cast<uint64_t>(num_resolved));
511     return num_resolved;
512 }
513 
514 size_t
515 SBBreakpoint::GetNumLocations() const
516 {
517     size_t num_locs = 0;
518     if (m_opaque_sp)
519     {
520         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
521         num_locs = m_opaque_sp->GetNumLocations();
522     }
523     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
524     if (log)
525         log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64,
526                      static_cast<void*>(m_opaque_sp.get()),
527                      static_cast<uint64_t>(num_locs));
528     return num_locs;
529 }
530 
531 bool
532 SBBreakpoint::GetDescription (SBStream &s)
533 {
534     if (m_opaque_sp)
535     {
536         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
537         s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
538         m_opaque_sp->GetResolverDescription (s.get());
539         m_opaque_sp->GetFilterDescription (s.get());
540         const size_t num_locations = m_opaque_sp->GetNumLocations ();
541         s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
542         return true;
543     }
544     s.Printf ("No value");
545     return false;
546 }
547 
548 bool
549 SBBreakpoint::PrivateBreakpointHitCallback
550 (
551     void *baton,
552     StoppointCallbackContext *ctx,
553     lldb::user_id_t break_id,
554     lldb::user_id_t break_loc_id
555 )
556 {
557     ExecutionContext exe_ctx (ctx->exe_ctx_ref);
558     BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
559     if (baton && bp_sp)
560     {
561         CallbackData *data = (CallbackData *)baton;
562         lldb_private::Breakpoint *bp = bp_sp.get();
563         if (bp && data->callback)
564         {
565             Process *process = exe_ctx.GetProcessPtr();
566             if (process)
567             {
568                 SBProcess sb_process (process->shared_from_this());
569                 SBThread sb_thread;
570                 SBBreakpointLocation sb_location;
571                 assert (bp_sp);
572                 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
573                 Thread *thread = exe_ctx.GetThreadPtr();
574                 if (thread)
575                     sb_thread.SetThread(thread->shared_from_this());
576 
577                 return data->callback (data->callback_baton,
578                                           sb_process,
579                                           sb_thread,
580                                           sb_location);
581             }
582         }
583     }
584     return true;    // Return true if we should stop at this breakpoint
585 }
586 
587 void
588 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
589 {
590     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
591 
592     if (log)
593     {
594         void *pointer = &callback;
595         log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)",
596                      static_cast<void*>(m_opaque_sp.get()),
597                      *static_cast<void**>(&pointer), static_cast<void*>(baton));
598     }
599 
600     if (m_opaque_sp)
601     {
602         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
603         BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
604         m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
605     }
606 }
607 
608 void
609 SBBreakpoint::SetScriptCallbackFunction (const char *callback_function_name)
610 {
611     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
612 
613     if (log)
614         log->Printf ("SBBreakpoint(%p)::SetScriptCallbackFunction (callback=%s)",
615                      static_cast<void*>(m_opaque_sp.get()),
616                      callback_function_name);
617 
618     if (m_opaque_sp)
619     {
620         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
621         BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
622         m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options,
623                                                                                                                                                    callback_function_name);
624     }
625 }
626 
627 SBError
628 SBBreakpoint::SetScriptCallbackBody (const char *callback_body_text)
629 {
630     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
631 
632     if (log)
633         log->Printf ("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)",
634                      static_cast<void*>(m_opaque_sp.get()), callback_body_text);
635 
636     SBError sb_error;
637     if (m_opaque_sp)
638     {
639         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
640         BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
641         Error error =  m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
642                                                                                                                                     callback_body_text);
643         sb_error.SetError(error);
644     }
645     else
646         sb_error.SetErrorString("invalid breakpoint");
647 
648     return sb_error;
649 }
650 
651 lldb_private::Breakpoint *
652 SBBreakpoint::operator->() const
653 {
654     return m_opaque_sp.get();
655 }
656 
657 lldb_private::Breakpoint *
658 SBBreakpoint::get() const
659 {
660     return m_opaque_sp.get();
661 }
662 
663 lldb::BreakpointSP &
664 SBBreakpoint::operator *()
665 {
666     return m_opaque_sp;
667 }
668 
669 const lldb::BreakpointSP &
670 SBBreakpoint::operator *() const
671 {
672     return m_opaque_sp;
673 }
674 
675 bool
676 SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event)
677 {
678     return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL;
679 
680 }
681 
682 BreakpointEventType
683 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
684 {
685     if (event.IsValid())
686         return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
687     return eBreakpointEventTypeInvalidType;
688 }
689 
690 SBBreakpoint
691 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
692 {
693     SBBreakpoint sb_breakpoint;
694     if (event.IsValid())
695         sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
696     return sb_breakpoint;
697 }
698 
699 SBBreakpointLocation
700 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
701 {
702     SBBreakpointLocation sb_breakpoint_loc;
703     if (event.IsValid())
704         sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
705     return sb_breakpoint_loc;
706 }
707 
708 uint32_t
709 SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event)
710 {
711     uint32_t num_locations = 0;
712     if (event.IsValid())
713         num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP()));
714     return num_locations;
715 }
716 
717 
718