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