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
573   ::SetCallback(SBBreakpointHitCallback callback,
574   void *baton) {
575   BreakpointSP bkpt_sp = GetSP();
576 
577   if (bkpt_sp) {
578     std::lock_guard<std::recursive_mutex> guard(
579         bkpt_sp->GetTarget().GetAPIMutex());
580     BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));
581     bkpt_sp->SetCallback(SBBreakpointCallbackBaton
582       ::PrivateBreakpointHitCallback, baton_sp,
583                          false);
584   }
585 }
586 
587 void SBBreakpoint::SetScriptCallbackFunction(
588     const char *callback_function_name) {
589   LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
590                      (const char *), callback_function_name);
591 
592   BreakpointSP bkpt_sp = GetSP();
593 
594   if (bkpt_sp) {
595     std::lock_guard<std::recursive_mutex> guard(
596         bkpt_sp->GetTarget().GetAPIMutex());
597     BreakpointOptions *bp_options = bkpt_sp->GetOptions();
598     bkpt_sp->GetTarget()
599         .GetDebugger()
600         .GetCommandInterpreter()
601         .GetScriptInterpreter()
602         ->SetBreakpointCommandCallbackFunction(bp_options,
603                                                callback_function_name);
604   }
605 }
606 
607 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
608   LLDB_RECORD_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackBody,
609                      (const char *), callback_body_text);
610 
611   BreakpointSP bkpt_sp = GetSP();
612 
613   SBError sb_error;
614   if (bkpt_sp) {
615     std::lock_guard<std::recursive_mutex> guard(
616         bkpt_sp->GetTarget().GetAPIMutex());
617     BreakpointOptions *bp_options = bkpt_sp->GetOptions();
618     Status error =
619         bkpt_sp->GetTarget()
620             .GetDebugger()
621             .GetCommandInterpreter()
622             .GetScriptInterpreter()
623             ->SetBreakpointCommandCallback(bp_options, callback_body_text);
624     sb_error.SetError(error);
625   } else
626     sb_error.SetErrorString("invalid breakpoint");
627 
628   return LLDB_RECORD_RESULT(sb_error);
629 }
630 
631 bool SBBreakpoint::AddName(const char *new_name) {
632   LLDB_RECORD_METHOD(bool, SBBreakpoint, AddName, (const char *), new_name);
633 
634   BreakpointSP bkpt_sp = GetSP();
635 
636   if (bkpt_sp) {
637     std::lock_guard<std::recursive_mutex> guard(
638         bkpt_sp->GetTarget().GetAPIMutex());
639     Status error; // Think I'm just going to swallow the error here, it's
640                   // probably more annoying to have to provide it.
641     bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error);
642     if (error.Fail())
643       return false;
644   }
645 
646   return true;
647 }
648 
649 void SBBreakpoint::RemoveName(const char *name_to_remove) {
650   LLDB_RECORD_METHOD(void, SBBreakpoint, RemoveName, (const char *),
651                      name_to_remove);
652 
653   BreakpointSP bkpt_sp = GetSP();
654 
655   if (bkpt_sp) {
656     std::lock_guard<std::recursive_mutex> guard(
657         bkpt_sp->GetTarget().GetAPIMutex());
658     bkpt_sp->GetTarget().RemoveNameFromBreakpoint(bkpt_sp,
659                                                   ConstString(name_to_remove));
660   }
661 }
662 
663 bool SBBreakpoint::MatchesName(const char *name) {
664   LLDB_RECORD_METHOD(bool, SBBreakpoint, MatchesName, (const char *), name);
665 
666   BreakpointSP bkpt_sp = GetSP();
667 
668   if (bkpt_sp) {
669     std::lock_guard<std::recursive_mutex> guard(
670         bkpt_sp->GetTarget().GetAPIMutex());
671     return bkpt_sp->MatchesName(name);
672   }
673 
674   return false;
675 }
676 
677 void SBBreakpoint::GetNames(SBStringList &names) {
678   LLDB_RECORD_METHOD(void, SBBreakpoint, GetNames, (lldb::SBStringList &),
679                      names);
680 
681   BreakpointSP bkpt_sp = GetSP();
682 
683   if (bkpt_sp) {
684     std::lock_guard<std::recursive_mutex> guard(
685         bkpt_sp->GetTarget().GetAPIMutex());
686     std::vector<std::string> names_vec;
687     bkpt_sp->GetNames(names_vec);
688     for (std::string name : names_vec) {
689       names.AppendString(name.c_str());
690     }
691   }
692 }
693 
694 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) {
695   LLDB_RECORD_STATIC_METHOD(bool, SBBreakpoint, EventIsBreakpointEvent,
696                             (const lldb::SBEvent &), event);
697 
698   return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) !=
699          nullptr;
700 }
701 
702 BreakpointEventType
703 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) {
704   LLDB_RECORD_STATIC_METHOD(lldb::BreakpointEventType, SBBreakpoint,
705                             GetBreakpointEventTypeFromEvent,
706                             (const lldb::SBEvent &), event);
707 
708   if (event.IsValid())
709     return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
710         event.GetSP());
711   return eBreakpointEventTypeInvalidType;
712 }
713 
714 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) {
715   LLDB_RECORD_STATIC_METHOD(lldb::SBBreakpoint, SBBreakpoint,
716                             GetBreakpointFromEvent, (const lldb::SBEvent &),
717                             event);
718 
719   if (event.IsValid())
720     return LLDB_RECORD_RESULT(
721         SBBreakpoint(Breakpoint::BreakpointEventData::GetBreakpointFromEvent(
722             event.GetSP())));
723   return LLDB_RECORD_RESULT(SBBreakpoint());
724 }
725 
726 SBBreakpointLocation
727 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
728                                                     uint32_t loc_idx) {
729   LLDB_RECORD_STATIC_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
730                             GetBreakpointLocationAtIndexFromEvent,
731                             (const lldb::SBEvent &, uint32_t), event, loc_idx);
732 
733   SBBreakpointLocation sb_breakpoint_loc;
734   if (event.IsValid())
735     sb_breakpoint_loc.SetLocation(
736         Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
737             event.GetSP(), loc_idx));
738   return LLDB_RECORD_RESULT(sb_breakpoint_loc);
739 }
740 
741 uint32_t
742 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) {
743   LLDB_RECORD_STATIC_METHOD(uint32_t, SBBreakpoint,
744                             GetNumBreakpointLocationsFromEvent,
745                             (const lldb::SBEvent &), event);
746 
747   uint32_t num_locations = 0;
748   if (event.IsValid())
749     num_locations =
750         (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
751             event.GetSP()));
752   return num_locations;
753 }
754 
755 bool SBBreakpoint::IsHardware() const {
756   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsHardware);
757 
758   BreakpointSP bkpt_sp = GetSP();
759   if (bkpt_sp)
760     return bkpt_sp->IsHardware();
761   return false;
762 }
763 
764 BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); }
765 
766 // This is simple collection of breakpoint id's and their target.
767 class SBBreakpointListImpl {
768 public:
769   SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() {
770     if (target_sp && target_sp->IsValid())
771       m_target_wp = target_sp;
772   }
773 
774   ~SBBreakpointListImpl() = default;
775 
776   size_t GetSize() { return m_break_ids.size(); }
777 
778   BreakpointSP GetBreakpointAtIndex(size_t idx) {
779     if (idx >= m_break_ids.size())
780       return BreakpointSP();
781     TargetSP target_sp = m_target_wp.lock();
782     if (!target_sp)
783       return BreakpointSP();
784     lldb::break_id_t bp_id = m_break_ids[idx];
785     return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
786   }
787 
788   BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) {
789     TargetSP target_sp = m_target_wp.lock();
790     if (!target_sp)
791       return BreakpointSP();
792 
793     for (lldb::break_id_t &break_id : m_break_ids) {
794       if (break_id == desired_id)
795         return target_sp->GetBreakpointList().FindBreakpointByID(break_id);
796     }
797     return BreakpointSP();
798   }
799 
800   bool Append(BreakpointSP bkpt) {
801     TargetSP target_sp = m_target_wp.lock();
802     if (!target_sp || !bkpt)
803       return false;
804     if (bkpt->GetTargetSP() != target_sp)
805       return false;
806     m_break_ids.push_back(bkpt->GetID());
807     return true;
808   }
809 
810   bool AppendIfUnique(BreakpointSP bkpt) {
811     TargetSP target_sp = m_target_wp.lock();
812     if (!target_sp || !bkpt)
813       return false;
814     if (bkpt->GetTargetSP() != target_sp)
815       return false;
816     lldb::break_id_t bp_id = bkpt->GetID();
817     if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) ==
818         m_break_ids.end())
819       return false;
820 
821     m_break_ids.push_back(bkpt->GetID());
822     return true;
823   }
824 
825   bool AppendByID(lldb::break_id_t id) {
826     TargetSP target_sp = m_target_wp.lock();
827     if (!target_sp)
828       return false;
829     if (id == LLDB_INVALID_BREAK_ID)
830       return false;
831     m_break_ids.push_back(id);
832     return true;
833   }
834 
835   void Clear() { m_break_ids.clear(); }
836 
837   void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) {
838     for (lldb::break_id_t id : m_break_ids) {
839       bp_list.AddBreakpointID(BreakpointID(id));
840     }
841   }
842 
843   TargetSP GetTarget() { return m_target_wp.lock(); }
844 
845 private:
846   std::vector<lldb::break_id_t> m_break_ids;
847   TargetWP m_target_wp;
848 };
849 
850 SBBreakpointList::SBBreakpointList(SBTarget &target)
851     : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) {
852   LLDB_RECORD_CONSTRUCTOR(SBBreakpointList, (lldb::SBTarget &), target);
853 }
854 
855 SBBreakpointList::~SBBreakpointList() {}
856 
857 size_t SBBreakpointList::GetSize() const {
858   LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBBreakpointList, GetSize);
859 
860   if (!m_opaque_sp)
861     return 0;
862   else
863     return m_opaque_sp->GetSize();
864 }
865 
866 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
867   LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, GetBreakpointAtIndex,
868                      (size_t), idx);
869 
870   if (!m_opaque_sp)
871     return LLDB_RECORD_RESULT(SBBreakpoint());
872 
873   BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx);
874   return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp));
875 }
876 
877 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) {
878   LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, FindBreakpointByID,
879                      (lldb::break_id_t), id);
880 
881   if (!m_opaque_sp)
882     return LLDB_RECORD_RESULT(SBBreakpoint());
883   BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id);
884   return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp));
885 }
886 
887 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
888   LLDB_RECORD_METHOD(void, SBBreakpointList, Append,
889                      (const lldb::SBBreakpoint &), sb_bkpt);
890 
891   if (!sb_bkpt.IsValid())
892     return;
893   if (!m_opaque_sp)
894     return;
895   m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock());
896 }
897 
898 void SBBreakpointList::AppendByID(lldb::break_id_t id) {
899   LLDB_RECORD_METHOD(void, SBBreakpointList, AppendByID, (lldb::break_id_t),
900                      id);
901 
902   if (!m_opaque_sp)
903     return;
904   m_opaque_sp->AppendByID(id);
905 }
906 
907 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) {
908   LLDB_RECORD_METHOD(bool, SBBreakpointList, AppendIfUnique,
909                      (const lldb::SBBreakpoint &), sb_bkpt);
910 
911   if (!sb_bkpt.IsValid())
912     return false;
913   if (!m_opaque_sp)
914     return false;
915   return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP());
916 }
917 
918 void SBBreakpointList::Clear() {
919   LLDB_RECORD_METHOD_NO_ARGS(void, SBBreakpointList, Clear);
920 
921   if (m_opaque_sp)
922     m_opaque_sp->Clear();
923 }
924 
925 void SBBreakpointList::CopyToBreakpointIDList(
926     lldb_private::BreakpointIDList &bp_id_list) {
927   if (m_opaque_sp)
928     m_opaque_sp->CopyToBreakpointIDList(bp_id_list);
929 }
930