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