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