]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp
Merge llvm trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / API / SBBreakpoint.cpp
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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/API/SBBreakpoint.h"
15 #include "lldb/API/SBBreakpointLocation.h"
16 #include "lldb/API/SBDebugger.h"
17 #include "lldb/API/SBEvent.h"
18 #include "lldb/API/SBProcess.h"
19 #include "lldb/API/SBStream.h"
20 #include "lldb/API/SBStringList.h"
21 #include "lldb/API/SBThread.h"
22
23 #include "lldb/Breakpoint/Breakpoint.h"
24 #include "lldb/Breakpoint/BreakpointIDList.h"
25 #include "lldb/Breakpoint/BreakpointLocation.h"
26 #include "lldb/Breakpoint/StoppointCallbackContext.h"
27 #include "lldb/Core/Address.h"
28 #include "lldb/Core/Debugger.h"
29 #include "lldb/Core/Log.h"
30 #include "lldb/Core/Stream.h"
31 #include "lldb/Core/StreamFile.h"
32 #include "lldb/Interpreter/CommandInterpreter.h"
33 #include "lldb/Interpreter/ScriptInterpreter.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/SectionLoadList.h"
36 #include "lldb/Target/Target.h"
37 #include "lldb/Target/Thread.h"
38 #include "lldb/Target/ThreadSpec.h"
39
40 #include "lldb/lldb-enumerations.h"
41
42 #include "llvm/ADT/STLExtras.h"
43
44 using namespace lldb;
45 using namespace lldb_private;
46
47 struct CallbackData {
48   SBBreakpoint::BreakpointHitCallback callback;
49   void *callback_baton;
50 };
51
52 class SBBreakpointCallbackBaton : public TypedBaton<CallbackData> {
53 public:
54   SBBreakpointCallbackBaton(SBBreakpoint::BreakpointHitCallback callback,
55                             void *baton)
56       : TypedBaton(llvm::make_unique<CallbackData>()) {
57     getItem()->callback = callback;
58     getItem()->callback_baton = baton;
59   }
60 };
61
62 SBBreakpoint::SBBreakpoint() : m_opaque_sp() {}
63
64 SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs)
65     : m_opaque_sp(rhs.m_opaque_sp) {}
66
67 SBBreakpoint::SBBreakpoint(const lldb::BreakpointSP &bp_sp)
68     : m_opaque_sp(bp_sp) {}
69
70 SBBreakpoint::~SBBreakpoint() = default;
71
72 const SBBreakpoint &SBBreakpoint::operator=(const SBBreakpoint &rhs) {
73   if (this != &rhs)
74     m_opaque_sp = rhs.m_opaque_sp;
75   return *this;
76 }
77
78 bool SBBreakpoint::operator==(const lldb::SBBreakpoint &rhs) {
79   if (m_opaque_sp && rhs.m_opaque_sp)
80     return m_opaque_sp.get() == rhs.m_opaque_sp.get();
81   return false;
82 }
83
84 bool SBBreakpoint::operator!=(const lldb::SBBreakpoint &rhs) {
85   if (m_opaque_sp && rhs.m_opaque_sp)
86     return m_opaque_sp.get() != rhs.m_opaque_sp.get();
87   return (m_opaque_sp && !rhs.m_opaque_sp) || (rhs.m_opaque_sp && !m_opaque_sp);
88 }
89
90 break_id_t SBBreakpoint::GetID() const {
91   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
92
93   break_id_t break_id = LLDB_INVALID_BREAK_ID;
94   if (m_opaque_sp)
95     break_id = m_opaque_sp->GetID();
96
97   if (log) {
98     if (break_id == LLDB_INVALID_BREAK_ID)
99       log->Printf("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID",
100                   static_cast<void *>(m_opaque_sp.get()));
101     else
102       log->Printf("SBBreakpoint(%p)::GetID () => %u",
103                   static_cast<void *>(m_opaque_sp.get()), break_id);
104   }
105
106   return break_id;
107 }
108
109 bool SBBreakpoint::IsValid() const {
110   if (!m_opaque_sp)
111     return false;
112   else if (m_opaque_sp->GetTarget().GetBreakpointByID(m_opaque_sp->GetID()))
113     return true;
114   else
115     return false;
116 }
117
118 void SBBreakpoint::ClearAllBreakpointSites() {
119   if (m_opaque_sp) {
120     std::lock_guard<std::recursive_mutex> guard(
121         m_opaque_sp->GetTarget().GetAPIMutex());
122     m_opaque_sp->ClearAllBreakpointSites();
123   }
124 }
125
126 SBBreakpointLocation SBBreakpoint::FindLocationByAddress(addr_t vm_addr) {
127   SBBreakpointLocation sb_bp_location;
128
129   if (m_opaque_sp) {
130     if (vm_addr != LLDB_INVALID_ADDRESS) {
131       std::lock_guard<std::recursive_mutex> guard(
132           m_opaque_sp->GetTarget().GetAPIMutex());
133       Address address;
134       Target &target = m_opaque_sp->GetTarget();
135       if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) {
136         address.SetRawAddress(vm_addr);
137       }
138       sb_bp_location.SetLocation(m_opaque_sp->FindLocationByAddress(address));
139     }
140   }
141   return sb_bp_location;
142 }
143
144 break_id_t SBBreakpoint::FindLocationIDByAddress(addr_t vm_addr) {
145   break_id_t break_id = LLDB_INVALID_BREAK_ID;
146
147   if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS) {
148     std::lock_guard<std::recursive_mutex> guard(
149         m_opaque_sp->GetTarget().GetAPIMutex());
150     Address address;
151     Target &target = m_opaque_sp->GetTarget();
152     if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) {
153       address.SetRawAddress(vm_addr);
154     }
155     break_id = m_opaque_sp->FindLocationIDByAddress(address);
156   }
157
158   return break_id;
159 }
160
161 SBBreakpointLocation SBBreakpoint::FindLocationByID(break_id_t bp_loc_id) {
162   SBBreakpointLocation sb_bp_location;
163
164   if (m_opaque_sp) {
165     std::lock_guard<std::recursive_mutex> guard(
166         m_opaque_sp->GetTarget().GetAPIMutex());
167     sb_bp_location.SetLocation(m_opaque_sp->FindLocationByID(bp_loc_id));
168   }
169
170   return sb_bp_location;
171 }
172
173 SBBreakpointLocation SBBreakpoint::GetLocationAtIndex(uint32_t index) {
174   SBBreakpointLocation sb_bp_location;
175
176   if (m_opaque_sp) {
177     std::lock_guard<std::recursive_mutex> guard(
178         m_opaque_sp->GetTarget().GetAPIMutex());
179     sb_bp_location.SetLocation(m_opaque_sp->GetLocationAtIndex(index));
180   }
181
182   return sb_bp_location;
183 }
184
185 void SBBreakpoint::SetEnabled(bool enable) {
186   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
187
188   if (log)
189     log->Printf("SBBreakpoint(%p)::SetEnabled (enabled=%i)",
190                 static_cast<void *>(m_opaque_sp.get()), enable);
191
192   if (m_opaque_sp) {
193     std::lock_guard<std::recursive_mutex> guard(
194         m_opaque_sp->GetTarget().GetAPIMutex());
195     m_opaque_sp->SetEnabled(enable);
196   }
197 }
198
199 bool SBBreakpoint::IsEnabled() {
200   if (m_opaque_sp) {
201     std::lock_guard<std::recursive_mutex> guard(
202         m_opaque_sp->GetTarget().GetAPIMutex());
203     return m_opaque_sp->IsEnabled();
204   } else
205     return false;
206 }
207
208 void SBBreakpoint::SetOneShot(bool one_shot) {
209   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
210
211   if (log)
212     log->Printf("SBBreakpoint(%p)::SetOneShot (one_shot=%i)",
213                 static_cast<void *>(m_opaque_sp.get()), one_shot);
214
215   if (m_opaque_sp) {
216     std::lock_guard<std::recursive_mutex> guard(
217         m_opaque_sp->GetTarget().GetAPIMutex());
218     m_opaque_sp->SetOneShot(one_shot);
219   }
220 }
221
222 bool SBBreakpoint::IsOneShot() const {
223   if (m_opaque_sp) {
224     std::lock_guard<std::recursive_mutex> guard(
225         m_opaque_sp->GetTarget().GetAPIMutex());
226     return m_opaque_sp->IsOneShot();
227   } else
228     return false;
229 }
230
231 bool SBBreakpoint::IsInternal() {
232   if (m_opaque_sp) {
233     std::lock_guard<std::recursive_mutex> guard(
234         m_opaque_sp->GetTarget().GetAPIMutex());
235     return m_opaque_sp->IsInternal();
236   } else
237     return false;
238 }
239
240 void SBBreakpoint::SetIgnoreCount(uint32_t count) {
241   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
242
243   if (log)
244     log->Printf("SBBreakpoint(%p)::SetIgnoreCount (count=%u)",
245                 static_cast<void *>(m_opaque_sp.get()), count);
246
247   if (m_opaque_sp) {
248     std::lock_guard<std::recursive_mutex> guard(
249         m_opaque_sp->GetTarget().GetAPIMutex());
250     m_opaque_sp->SetIgnoreCount(count);
251   }
252 }
253
254 void SBBreakpoint::SetCondition(const char *condition) {
255   if (m_opaque_sp) {
256     std::lock_guard<std::recursive_mutex> guard(
257         m_opaque_sp->GetTarget().GetAPIMutex());
258     m_opaque_sp->SetCondition(condition);
259   }
260 }
261
262 const char *SBBreakpoint::GetCondition() {
263   if (m_opaque_sp) {
264     std::lock_guard<std::recursive_mutex> guard(
265         m_opaque_sp->GetTarget().GetAPIMutex());
266     return m_opaque_sp->GetConditionText();
267   }
268   return nullptr;
269 }
270
271 uint32_t SBBreakpoint::GetHitCount() const {
272   uint32_t count = 0;
273   if (m_opaque_sp) {
274     std::lock_guard<std::recursive_mutex> guard(
275         m_opaque_sp->GetTarget().GetAPIMutex());
276     count = m_opaque_sp->GetHitCount();
277   }
278
279   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
280   if (log)
281     log->Printf("SBBreakpoint(%p)::GetHitCount () => %u",
282                 static_cast<void *>(m_opaque_sp.get()), count);
283
284   return count;
285 }
286
287 uint32_t SBBreakpoint::GetIgnoreCount() const {
288   uint32_t count = 0;
289   if (m_opaque_sp) {
290     std::lock_guard<std::recursive_mutex> guard(
291         m_opaque_sp->GetTarget().GetAPIMutex());
292     count = m_opaque_sp->GetIgnoreCount();
293   }
294
295   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
296   if (log)
297     log->Printf("SBBreakpoint(%p)::GetIgnoreCount () => %u",
298                 static_cast<void *>(m_opaque_sp.get()), count);
299
300   return count;
301 }
302
303 void SBBreakpoint::SetThreadID(tid_t tid) {
304   if (m_opaque_sp) {
305     std::lock_guard<std::recursive_mutex> guard(
306         m_opaque_sp->GetTarget().GetAPIMutex());
307     m_opaque_sp->SetThreadID(tid);
308   }
309   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
310   if (log)
311     log->Printf("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")",
312                 static_cast<void *>(m_opaque_sp.get()), tid);
313 }
314
315 tid_t SBBreakpoint::GetThreadID() {
316   tid_t tid = LLDB_INVALID_THREAD_ID;
317   if (m_opaque_sp) {
318     std::lock_guard<std::recursive_mutex> guard(
319         m_opaque_sp->GetTarget().GetAPIMutex());
320     tid = m_opaque_sp->GetThreadID();
321   }
322
323   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
324   if (log)
325     log->Printf("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64,
326                 static_cast<void *>(m_opaque_sp.get()), tid);
327   return tid;
328 }
329
330 void SBBreakpoint::SetThreadIndex(uint32_t index) {
331   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
332   if (log)
333     log->Printf("SBBreakpoint(%p)::SetThreadIndex (%u)",
334                 static_cast<void *>(m_opaque_sp.get()), index);
335   if (m_opaque_sp) {
336     std::lock_guard<std::recursive_mutex> guard(
337         m_opaque_sp->GetTarget().GetAPIMutex());
338     m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex(index);
339   }
340 }
341
342 uint32_t SBBreakpoint::GetThreadIndex() const {
343   uint32_t thread_idx = UINT32_MAX;
344   if (m_opaque_sp) {
345     std::lock_guard<std::recursive_mutex> guard(
346         m_opaque_sp->GetTarget().GetAPIMutex());
347     const ThreadSpec *thread_spec =
348         m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
349     if (thread_spec != nullptr)
350       thread_idx = thread_spec->GetIndex();
351   }
352   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
353   if (log)
354     log->Printf("SBBreakpoint(%p)::GetThreadIndex () => %u",
355                 static_cast<void *>(m_opaque_sp.get()), thread_idx);
356
357   return thread_idx;
358 }
359
360 void SBBreakpoint::SetThreadName(const char *thread_name) {
361   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
362   if (log)
363     log->Printf("SBBreakpoint(%p)::SetThreadName (%s)",
364                 static_cast<void *>(m_opaque_sp.get()), thread_name);
365
366   if (m_opaque_sp) {
367     std::lock_guard<std::recursive_mutex> guard(
368         m_opaque_sp->GetTarget().GetAPIMutex());
369     m_opaque_sp->GetOptions()->GetThreadSpec()->SetName(thread_name);
370   }
371 }
372
373 const char *SBBreakpoint::GetThreadName() const {
374   const char *name = nullptr;
375   if (m_opaque_sp) {
376     std::lock_guard<std::recursive_mutex> guard(
377         m_opaque_sp->GetTarget().GetAPIMutex());
378     const ThreadSpec *thread_spec =
379         m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
380     if (thread_spec != nullptr)
381       name = thread_spec->GetName();
382   }
383   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
384   if (log)
385     log->Printf("SBBreakpoint(%p)::GetThreadName () => %s",
386                 static_cast<void *>(m_opaque_sp.get()), name);
387
388   return name;
389 }
390
391 void SBBreakpoint::SetQueueName(const char *queue_name) {
392   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
393   if (log)
394     log->Printf("SBBreakpoint(%p)::SetQueueName (%s)",
395                 static_cast<void *>(m_opaque_sp.get()), queue_name);
396   if (m_opaque_sp) {
397     std::lock_guard<std::recursive_mutex> guard(
398         m_opaque_sp->GetTarget().GetAPIMutex());
399     m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name);
400   }
401 }
402
403 const char *SBBreakpoint::GetQueueName() const {
404   const char *name = nullptr;
405   if (m_opaque_sp) {
406     std::lock_guard<std::recursive_mutex> guard(
407         m_opaque_sp->GetTarget().GetAPIMutex());
408     const ThreadSpec *thread_spec =
409         m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
410     if (thread_spec)
411       name = thread_spec->GetQueueName();
412   }
413   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
414   if (log)
415     log->Printf("SBBreakpoint(%p)::GetQueueName () => %s",
416                 static_cast<void *>(m_opaque_sp.get()), name);
417
418   return name;
419 }
420
421 size_t SBBreakpoint::GetNumResolvedLocations() const {
422   size_t num_resolved = 0;
423   if (m_opaque_sp) {
424     std::lock_guard<std::recursive_mutex> guard(
425         m_opaque_sp->GetTarget().GetAPIMutex());
426     num_resolved = m_opaque_sp->GetNumResolvedLocations();
427   }
428   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
429   if (log)
430     log->Printf("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64,
431                 static_cast<void *>(m_opaque_sp.get()),
432                 static_cast<uint64_t>(num_resolved));
433   return num_resolved;
434 }
435
436 size_t SBBreakpoint::GetNumLocations() const {
437   size_t num_locs = 0;
438   if (m_opaque_sp) {
439     std::lock_guard<std::recursive_mutex> guard(
440         m_opaque_sp->GetTarget().GetAPIMutex());
441     num_locs = m_opaque_sp->GetNumLocations();
442   }
443   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
444   if (log)
445     log->Printf("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64,
446                 static_cast<void *>(m_opaque_sp.get()),
447                 static_cast<uint64_t>(num_locs));
448   return num_locs;
449 }
450
451 void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) {
452   if (!m_opaque_sp)
453     return;
454   if (commands.GetSize() == 0)
455     return;
456
457   std::lock_guard<std::recursive_mutex> guard(
458       m_opaque_sp->GetTarget().GetAPIMutex());
459   std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
460       new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
461
462   m_opaque_sp->GetOptions()->SetCommandDataCallback(cmd_data_up);
463 }
464
465 bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) {
466   if (!m_opaque_sp)
467     return false;
468   StringList command_list;
469   bool has_commands =
470       m_opaque_sp->GetOptions()->GetCommandLineCallbacks(command_list);
471   if (has_commands)
472     commands.AppendList(command_list);
473   return has_commands;
474 }
475
476 bool SBBreakpoint::GetDescription(SBStream &s) {
477   return GetDescription(s, true);
478 }
479
480 bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) {
481   if (m_opaque_sp) {
482     std::lock_guard<std::recursive_mutex> guard(
483         m_opaque_sp->GetTarget().GetAPIMutex());
484     s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
485     m_opaque_sp->GetResolverDescription(s.get());
486     m_opaque_sp->GetFilterDescription(s.get());
487     if (include_locations) {
488       const size_t num_locations = m_opaque_sp->GetNumLocations();
489       s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
490     }
491     return true;
492   }
493   s.Printf("No value");
494   return false;
495 }
496
497 bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton,
498                                                 StoppointCallbackContext *ctx,
499                                                 lldb::user_id_t break_id,
500                                                 lldb::user_id_t break_loc_id) {
501   ExecutionContext exe_ctx(ctx->exe_ctx_ref);
502   BreakpointSP bp_sp(
503       exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
504   if (baton && bp_sp) {
505     CallbackData *data = (CallbackData *)baton;
506     lldb_private::Breakpoint *bp = bp_sp.get();
507     if (bp && data->callback) {
508       Process *process = exe_ctx.GetProcessPtr();
509       if (process) {
510         SBProcess sb_process(process->shared_from_this());
511         SBThread sb_thread;
512         SBBreakpointLocation sb_location;
513         assert(bp_sp);
514         sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id));
515         Thread *thread = exe_ctx.GetThreadPtr();
516         if (thread)
517           sb_thread.SetThread(thread->shared_from_this());
518
519         return data->callback(data->callback_baton, sb_process, sb_thread,
520                               sb_location);
521       }
522     }
523   }
524   return true; // Return true if we should stop at this breakpoint
525 }
526
527 void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) {
528   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
529
530   if (log) {
531     void *pointer = &callback;
532     log->Printf("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)",
533                 static_cast<void *>(m_opaque_sp.get()),
534                 *static_cast<void **>(&pointer), static_cast<void *>(baton));
535   }
536
537   if (m_opaque_sp) {
538     std::lock_guard<std::recursive_mutex> guard(
539         m_opaque_sp->GetTarget().GetAPIMutex());
540     BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));
541     m_opaque_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback,
542                              baton_sp, false);
543   }
544 }
545
546 void SBBreakpoint::SetScriptCallbackFunction(
547     const char *callback_function_name) {
548   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
549
550   if (log)
551     log->Printf("SBBreakpoint(%p)::SetScriptCallbackFunction (callback=%s)",
552                 static_cast<void *>(m_opaque_sp.get()), callback_function_name);
553
554   if (m_opaque_sp) {
555     std::lock_guard<std::recursive_mutex> guard(
556         m_opaque_sp->GetTarget().GetAPIMutex());
557     BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
558     m_opaque_sp->GetTarget()
559         .GetDebugger()
560         .GetCommandInterpreter()
561         .GetScriptInterpreter()
562         ->SetBreakpointCommandCallbackFunction(bp_options,
563                                                callback_function_name);
564   }
565 }
566
567 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
568   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
569
570   if (log)
571     log->Printf("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)",
572                 static_cast<void *>(m_opaque_sp.get()), callback_body_text);
573
574   SBError sb_error;
575   if (m_opaque_sp) {
576     std::lock_guard<std::recursive_mutex> guard(
577         m_opaque_sp->GetTarget().GetAPIMutex());
578     BreakpointOptions *bp_options = m_opaque_sp->GetOptions();
579     Error error =
580         m_opaque_sp->GetTarget()
581             .GetDebugger()
582             .GetCommandInterpreter()
583             .GetScriptInterpreter()
584             ->SetBreakpointCommandCallback(bp_options, callback_body_text);
585     sb_error.SetError(error);
586   } else
587     sb_error.SetErrorString("invalid breakpoint");
588
589   return sb_error;
590 }
591
592 bool SBBreakpoint::AddName(const char *new_name) {
593   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
594
595   if (log)
596     log->Printf("SBBreakpoint(%p)::AddName (name=%s)",
597                 static_cast<void *>(m_opaque_sp.get()), new_name);
598
599   if (m_opaque_sp) {
600     std::lock_guard<std::recursive_mutex> guard(
601         m_opaque_sp->GetTarget().GetAPIMutex());
602     Error error; // Think I'm just going to swallow the error here, it's
603                  // probably more annoying to have to provide it.
604     return m_opaque_sp->AddName(new_name, error);
605   }
606
607   return false;
608 }
609
610 void SBBreakpoint::RemoveName(const char *name_to_remove) {
611   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
612
613   if (log)
614     log->Printf("SBBreakpoint(%p)::RemoveName (name=%s)",
615                 static_cast<void *>(m_opaque_sp.get()), name_to_remove);
616
617   if (m_opaque_sp) {
618     std::lock_guard<std::recursive_mutex> guard(
619         m_opaque_sp->GetTarget().GetAPIMutex());
620     m_opaque_sp->RemoveName(name_to_remove);
621   }
622 }
623
624 bool SBBreakpoint::MatchesName(const char *name) {
625   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
626
627   if (log)
628     log->Printf("SBBreakpoint(%p)::MatchesName (name=%s)",
629                 static_cast<void *>(m_opaque_sp.get()), name);
630
631   if (m_opaque_sp) {
632     std::lock_guard<std::recursive_mutex> guard(
633         m_opaque_sp->GetTarget().GetAPIMutex());
634     return m_opaque_sp->MatchesName(name);
635   }
636
637   return false;
638 }
639
640 void SBBreakpoint::GetNames(SBStringList &names) {
641   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
642
643   if (log)
644     log->Printf("SBBreakpoint(%p)::GetNames ()",
645                 static_cast<void *>(m_opaque_sp.get()));
646
647   if (m_opaque_sp) {
648     std::lock_guard<std::recursive_mutex> guard(
649         m_opaque_sp->GetTarget().GetAPIMutex());
650     std::vector<std::string> names_vec;
651     m_opaque_sp->GetNames(names_vec);
652     for (std::string name : names_vec) {
653       names.AppendString(name.c_str());
654     }
655   }
656 }
657
658 lldb_private::Breakpoint *SBBreakpoint::operator->() const {
659   return m_opaque_sp.get();
660 }
661
662 lldb_private::Breakpoint *SBBreakpoint::get() const {
663   return m_opaque_sp.get();
664 }
665
666 lldb::BreakpointSP &SBBreakpoint::operator*() { return m_opaque_sp; }
667
668 const lldb::BreakpointSP &SBBreakpoint::operator*() const {
669   return m_opaque_sp;
670 }
671
672 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) {
673   return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) !=
674          nullptr;
675 }
676
677 BreakpointEventType
678 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) {
679   if (event.IsValid())
680     return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
681         event.GetSP());
682   return eBreakpointEventTypeInvalidType;
683 }
684
685 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) {
686   SBBreakpoint sb_breakpoint;
687   if (event.IsValid())
688     sb_breakpoint.m_opaque_sp =
689         Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event.GetSP());
690   return sb_breakpoint;
691 }
692
693 SBBreakpointLocation
694 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
695                                                     uint32_t loc_idx) {
696   SBBreakpointLocation sb_breakpoint_loc;
697   if (event.IsValid())
698     sb_breakpoint_loc.SetLocation(
699         Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
700             event.GetSP(), loc_idx));
701   return sb_breakpoint_loc;
702 }
703
704 uint32_t
705 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) {
706   uint32_t num_locations = 0;
707   if (event.IsValid())
708     num_locations =
709         (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
710             event.GetSP()));
711   return num_locations;
712 }
713
714 // This is simple collection of breakpoint id's and their target.
715 class SBBreakpointListImpl {
716 public:
717   SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() {
718     if (target_sp && target_sp->IsValid())
719       m_target_wp = target_sp;
720   }
721
722   ~SBBreakpointListImpl() = default;
723
724   size_t GetSize() { return m_break_ids.size(); }
725
726   BreakpointSP GetBreakpointAtIndex(size_t idx) {
727     if (idx >= m_break_ids.size())
728       return BreakpointSP();
729     TargetSP target_sp = m_target_wp.lock();
730     if (!target_sp)
731       return BreakpointSP();
732     lldb::break_id_t bp_id = m_break_ids[idx];
733     return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
734   }
735
736   BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) {
737     TargetSP target_sp = m_target_wp.lock();
738     if (!target_sp)
739       return BreakpointSP();
740
741     for (lldb::break_id_t &break_id : m_break_ids) {
742       if (break_id == desired_id)
743         return target_sp->GetBreakpointList().FindBreakpointByID(break_id);
744     }
745     return BreakpointSP();
746   }
747
748   bool Append(Breakpoint &bkpt) {
749     TargetSP target_sp = m_target_wp.lock();
750     if (!target_sp)
751       return false;
752     if (bkpt.GetTargetSP() != target_sp)
753       return false;
754     m_break_ids.push_back(bkpt.GetID());
755     return true;
756   }
757
758   bool AppendIfUnique(Breakpoint &bkpt) {
759     TargetSP target_sp = m_target_wp.lock();
760     if (!target_sp)
761       return false;
762     if (bkpt.GetTargetSP() != target_sp)
763       return false;
764     lldb::break_id_t bp_id = bkpt.GetID();
765     if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) ==
766         m_break_ids.end())
767       return false;
768
769     m_break_ids.push_back(bkpt.GetID());
770     return true;
771   }
772
773   bool AppendByID(lldb::break_id_t id) {
774     TargetSP target_sp = m_target_wp.lock();
775     if (!target_sp)
776       return false;
777     if (id == LLDB_INVALID_BREAK_ID)
778       return false;
779     m_break_ids.push_back(id);
780     return true;
781   }
782
783   void Clear() { m_break_ids.clear(); }
784
785   void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) {
786     for (lldb::break_id_t id : m_break_ids) {
787       bp_list.AddBreakpointID(BreakpointID(id));
788     }
789   }
790
791   TargetSP GetTarget() { return m_target_wp.lock(); }
792
793 private:
794   std::vector<lldb::break_id_t> m_break_ids;
795   TargetWP m_target_wp;
796 };
797
798 SBBreakpointList::SBBreakpointList(SBTarget &target)
799     : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) {}
800
801 SBBreakpointList::~SBBreakpointList() {}
802
803 size_t SBBreakpointList::GetSize() const {
804   if (!m_opaque_sp)
805     return 0;
806   else
807     return m_opaque_sp->GetSize();
808 }
809
810 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
811   if (!m_opaque_sp)
812     return SBBreakpoint();
813
814   BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx);
815   return SBBreakpoint(bkpt_sp);
816 }
817
818 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) {
819   if (!m_opaque_sp)
820     return SBBreakpoint();
821   BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id);
822   return SBBreakpoint(bkpt_sp);
823 }
824
825 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
826   if (!sb_bkpt.IsValid())
827     return;
828   if (!m_opaque_sp)
829     return;
830   m_opaque_sp->Append(*sb_bkpt.get());
831 }
832
833 void SBBreakpointList::AppendByID(lldb::break_id_t id) {
834   if (!m_opaque_sp)
835     return;
836   m_opaque_sp->AppendByID(id);
837 }
838
839 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) {
840   if (!sb_bkpt.IsValid())
841     return false;
842   if (!m_opaque_sp)
843     return false;
844   return m_opaque_sp->AppendIfUnique(*sb_bkpt.get());
845 }
846
847 void SBBreakpointList::Clear() {
848   if (m_opaque_sp)
849     m_opaque_sp->Clear();
850 }
851
852 void SBBreakpointList::CopyToBreakpointIDList(
853     lldb_private::BreakpointIDList &bp_id_list) {
854   if (m_opaque_sp)
855     m_opaque_sp->CopyToBreakpointIDList(bp_id_list);
856 }