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