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