]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp
Merge ACPICA 20170929.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / API / SBBreakpoint.cpp
1 //===-- SBBreakpoint.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/API/SBBreakpoint.h"
15 #include "lldb/API/SBBreakpointLocation.h"
16 #include "lldb/API/SBDebugger.h"
17 #include "lldb/API/SBEvent.h"
18 #include "lldb/API/SBProcess.h"
19 #include "lldb/API/SBStream.h"
20 #include "lldb/API/SBStringList.h"
21 #include "lldb/API/SBThread.h"
22
23 #include "lldb/Breakpoint/Breakpoint.h"
24 #include "lldb/Breakpoint/BreakpointIDList.h"
25 #include "lldb/Breakpoint/BreakpointLocation.h"
26 #include "lldb/Breakpoint/StoppointCallbackContext.h"
27 #include "lldb/Core/Address.h"
28 #include "lldb/Core/Debugger.h"
29 #include "lldb/Core/StreamFile.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/Log.h"
38 #include "lldb/Utility/Stream.h"
39
40 #include "lldb/lldb-enumerations.h"
41
42 #include "llvm/ADT/STLExtras.h"
43
44 using namespace lldb;
45 using namespace lldb_private;
46
47 struct CallbackData {
48   SBBreakpoint::BreakpointHitCallback callback;
49   void *callback_baton;
50 };
51
52 class SBBreakpointCallbackBaton : public TypedBaton<CallbackData> {
53 public:
54   SBBreakpointCallbackBaton(SBBreakpoint::BreakpointHitCallback callback,
55                             void *baton)
56       : TypedBaton(llvm::make_unique<CallbackData>()) {
57     getItem()->callback = callback;
58     getItem()->callback_baton = baton;
59   }
60 };
61
62 SBBreakpoint::SBBreakpoint() {}
63
64 SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs)
65     : m_opaque_wp(rhs.m_opaque_wp) {}
66
67 SBBreakpoint::SBBreakpoint(const lldb::BreakpointSP &bp_sp)
68     : m_opaque_wp(bp_sp) {}
69
70 SBBreakpoint::~SBBreakpoint() = default;
71
72 const SBBreakpoint &SBBreakpoint::operator=(const SBBreakpoint &rhs) {
73   m_opaque_wp = rhs.m_opaque_wp;
74   return *this;
75 }
76
77 bool SBBreakpoint::operator==(const lldb::SBBreakpoint &rhs) {
78   return m_opaque_wp.lock() == rhs.m_opaque_wp.lock();
79 }
80
81 bool SBBreakpoint::operator!=(const lldb::SBBreakpoint &rhs) {
82   return m_opaque_wp.lock() != rhs.m_opaque_wp.lock();
83 }
84
85 break_id_t SBBreakpoint::GetID() const {
86   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
87
88   break_id_t break_id = LLDB_INVALID_BREAK_ID;
89   BreakpointSP bkpt_sp = GetSP();
90   if (bkpt_sp)
91     break_id = bkpt_sp->GetID();
92
93   LLDB_LOG(log, "breakpoint = {0}, id = {1}", bkpt_sp.get(), break_id);
94   return break_id;
95 }
96
97 bool SBBreakpoint::IsValid() const {
98   BreakpointSP bkpt_sp = GetSP();
99   if (!bkpt_sp)
100     return false;
101   else if (bkpt_sp->GetTarget().GetBreakpointByID(bkpt_sp->GetID()))
102     return true;
103   else
104     return false;
105 }
106
107 void SBBreakpoint::ClearAllBreakpointSites() {
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   SBBreakpointLocation sb_bp_location;
118
119   BreakpointSP bkpt_sp = GetSP();
120   if (bkpt_sp) {
121     if (vm_addr != LLDB_INVALID_ADDRESS) {
122       std::lock_guard<std::recursive_mutex> guard(
123           bkpt_sp->GetTarget().GetAPIMutex());
124       Address address;
125       Target &target = bkpt_sp->GetTarget();
126       if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) {
127         address.SetRawAddress(vm_addr);
128       }
129       sb_bp_location.SetLocation(bkpt_sp->FindLocationByAddress(address));
130     }
131   }
132   return sb_bp_location;
133 }
134
135 break_id_t SBBreakpoint::FindLocationIDByAddress(addr_t vm_addr) {
136   break_id_t break_id = LLDB_INVALID_BREAK_ID;
137   BreakpointSP bkpt_sp = GetSP();
138
139   if (bkpt_sp && vm_addr != LLDB_INVALID_ADDRESS) {
140     std::lock_guard<std::recursive_mutex> guard(
141         bkpt_sp->GetTarget().GetAPIMutex());
142     Address address;
143     Target &target = bkpt_sp->GetTarget();
144     if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) {
145       address.SetRawAddress(vm_addr);
146     }
147     break_id = bkpt_sp->FindLocationIDByAddress(address);
148   }
149
150   return break_id;
151 }
152
153 SBBreakpointLocation SBBreakpoint::FindLocationByID(break_id_t bp_loc_id) {
154   SBBreakpointLocation sb_bp_location;
155   BreakpointSP bkpt_sp = GetSP();
156
157   if (bkpt_sp) {
158     std::lock_guard<std::recursive_mutex> guard(
159         bkpt_sp->GetTarget().GetAPIMutex());
160     sb_bp_location.SetLocation(bkpt_sp->FindLocationByID(bp_loc_id));
161   }
162
163   return sb_bp_location;
164 }
165
166 SBBreakpointLocation SBBreakpoint::GetLocationAtIndex(uint32_t index) {
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->GetLocationAtIndex(index));
174   }
175
176   return sb_bp_location;
177 }
178
179 void SBBreakpoint::SetEnabled(bool enable) {
180   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
181   BreakpointSP bkpt_sp = GetSP();
182
183   LLDB_LOG(log, "breakpoint = {0}, enable = {1}", bkpt_sp.get(), enable);
184
185   if (bkpt_sp) {
186     std::lock_guard<std::recursive_mutex> guard(
187         bkpt_sp->GetTarget().GetAPIMutex());
188     bkpt_sp->SetEnabled(enable);
189   }
190 }
191
192 bool SBBreakpoint::IsEnabled() {
193   BreakpointSP bkpt_sp = GetSP();
194   if (bkpt_sp) {
195     std::lock_guard<std::recursive_mutex> guard(
196         bkpt_sp->GetTarget().GetAPIMutex());
197     return bkpt_sp->IsEnabled();
198   } else
199     return false;
200 }
201
202 void SBBreakpoint::SetOneShot(bool one_shot) {
203   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
204   BreakpointSP bkpt_sp = GetSP();
205
206   LLDB_LOG(log, "breakpoint = {0}, one_shot = {1}", bkpt_sp.get(), one_shot);
207
208   if (bkpt_sp) {
209     std::lock_guard<std::recursive_mutex> guard(
210         bkpt_sp->GetTarget().GetAPIMutex());
211     bkpt_sp->SetOneShot(one_shot);
212   }
213 }
214
215 bool SBBreakpoint::IsOneShot() const {
216   BreakpointSP bkpt_sp = GetSP();
217   if (bkpt_sp) {
218     std::lock_guard<std::recursive_mutex> guard(
219         bkpt_sp->GetTarget().GetAPIMutex());
220     return bkpt_sp->IsOneShot();
221   } else
222     return false;
223 }
224
225 bool SBBreakpoint::IsInternal() {
226   BreakpointSP bkpt_sp = GetSP();
227   if (bkpt_sp) {
228     std::lock_guard<std::recursive_mutex> guard(
229         bkpt_sp->GetTarget().GetAPIMutex());
230     return bkpt_sp->IsInternal();
231   } else
232     return false;
233 }
234
235 void SBBreakpoint::SetIgnoreCount(uint32_t count) {
236   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
237   BreakpointSP bkpt_sp = GetSP();
238
239   LLDB_LOG(log, "breakpoint = {0}, count = {1}", bkpt_sp.get(), count);
240
241   if (bkpt_sp) {
242     std::lock_guard<std::recursive_mutex> guard(
243         bkpt_sp->GetTarget().GetAPIMutex());
244     bkpt_sp->SetIgnoreCount(count);
245   }
246 }
247
248 void SBBreakpoint::SetCondition(const char *condition) {
249   BreakpointSP bkpt_sp = GetSP();
250   if (bkpt_sp) {
251     std::lock_guard<std::recursive_mutex> guard(
252         bkpt_sp->GetTarget().GetAPIMutex());
253     bkpt_sp->SetCondition(condition);
254   }
255 }
256
257 const char *SBBreakpoint::GetCondition() {
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->GetConditionText();
263   }
264   return nullptr;
265 }
266
267 uint32_t SBBreakpoint::GetHitCount() const {
268   uint32_t count = 0;
269   BreakpointSP bkpt_sp = GetSP();
270   if (bkpt_sp) {
271     std::lock_guard<std::recursive_mutex> guard(
272         bkpt_sp->GetTarget().GetAPIMutex());
273     count = bkpt_sp->GetHitCount();
274   }
275
276   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
277   LLDB_LOG(log, "breakpoint = {0}, count = {1}", bkpt_sp.get(), count);
278
279   return count;
280 }
281
282 uint32_t SBBreakpoint::GetIgnoreCount() const {
283   uint32_t count = 0;
284   BreakpointSP bkpt_sp = GetSP();
285   if (bkpt_sp) {
286     std::lock_guard<std::recursive_mutex> guard(
287         bkpt_sp->GetTarget().GetAPIMutex());
288     count = bkpt_sp->GetIgnoreCount();
289   }
290
291   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
292   LLDB_LOG(log, "breakpoint = {0}, count = {1}", bkpt_sp.get(), count);
293
294   return count;
295 }
296
297 void SBBreakpoint::SetThreadID(tid_t tid) {
298   BreakpointSP bkpt_sp = GetSP();
299   if (bkpt_sp) {
300     std::lock_guard<std::recursive_mutex> guard(
301         bkpt_sp->GetTarget().GetAPIMutex());
302     bkpt_sp->SetThreadID(tid);
303   }
304   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
305   LLDB_LOG(log, "breakpoint = {0}, tid = {1:x}", bkpt_sp.get(), tid);
306 }
307
308 tid_t SBBreakpoint::GetThreadID() {
309   tid_t tid = LLDB_INVALID_THREAD_ID;
310   BreakpointSP bkpt_sp = GetSP();
311   if (bkpt_sp) {
312     std::lock_guard<std::recursive_mutex> guard(
313         bkpt_sp->GetTarget().GetAPIMutex());
314     tid = bkpt_sp->GetThreadID();
315   }
316
317   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
318   LLDB_LOG(log, "breakpoint = {0}, tid = {1:x}", bkpt_sp.get(), tid);
319   return tid;
320 }
321
322 void SBBreakpoint::SetThreadIndex(uint32_t index) {
323   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
324   BreakpointSP bkpt_sp = GetSP();
325   LLDB_LOG(log, "breakpoint = {0}, index = {1}", bkpt_sp.get(), index);
326   if (bkpt_sp) {
327     std::lock_guard<std::recursive_mutex> guard(
328         bkpt_sp->GetTarget().GetAPIMutex());
329     bkpt_sp->GetOptions()->GetThreadSpec()->SetIndex(index);
330   }
331 }
332
333 uint32_t SBBreakpoint::GetThreadIndex() const {
334   uint32_t thread_idx = UINT32_MAX;
335   BreakpointSP bkpt_sp = GetSP();
336   if (bkpt_sp) {
337     std::lock_guard<std::recursive_mutex> guard(
338         bkpt_sp->GetTarget().GetAPIMutex());
339     const ThreadSpec *thread_spec =
340         bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
341     if (thread_spec != nullptr)
342       thread_idx = thread_spec->GetIndex();
343   }
344   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
345   LLDB_LOG(log, "breakpoint = {0}, index = {1}", bkpt_sp.get(), thread_idx);
346
347   return thread_idx;
348 }
349
350 void SBBreakpoint::SetThreadName(const char *thread_name) {
351   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
352   BreakpointSP bkpt_sp = GetSP();
353   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), thread_name);
354
355   if (bkpt_sp) {
356     std::lock_guard<std::recursive_mutex> guard(
357         bkpt_sp->GetTarget().GetAPIMutex());
358     bkpt_sp->GetOptions()->GetThreadSpec()->SetName(thread_name);
359   }
360 }
361
362 const char *SBBreakpoint::GetThreadName() const {
363   const char *name = nullptr;
364   BreakpointSP bkpt_sp = GetSP();
365   if (bkpt_sp) {
366     std::lock_guard<std::recursive_mutex> guard(
367         bkpt_sp->GetTarget().GetAPIMutex());
368     const ThreadSpec *thread_spec =
369         bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
370     if (thread_spec != nullptr)
371       name = thread_spec->GetName();
372   }
373   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
374   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name);
375
376   return name;
377 }
378
379 void SBBreakpoint::SetQueueName(const char *queue_name) {
380   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
381   BreakpointSP bkpt_sp = GetSP();
382   LLDB_LOG(log, "breakpoint = {0}, queue_name = {1}", bkpt_sp.get(),
383            queue_name);
384   if (bkpt_sp) {
385     std::lock_guard<std::recursive_mutex> guard(
386         bkpt_sp->GetTarget().GetAPIMutex());
387     bkpt_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name);
388   }
389 }
390
391 const char *SBBreakpoint::GetQueueName() const {
392   const char *name = nullptr;
393   BreakpointSP bkpt_sp = GetSP();
394   if (bkpt_sp) {
395     std::lock_guard<std::recursive_mutex> guard(
396         bkpt_sp->GetTarget().GetAPIMutex());
397     const ThreadSpec *thread_spec =
398         bkpt_sp->GetOptions()->GetThreadSpecNoCreate();
399     if (thread_spec)
400       name = thread_spec->GetQueueName();
401   }
402   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
403   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name);
404
405   return name;
406 }
407
408 size_t SBBreakpoint::GetNumResolvedLocations() const {
409   size_t num_resolved = 0;
410   BreakpointSP bkpt_sp = GetSP();
411   if (bkpt_sp) {
412     std::lock_guard<std::recursive_mutex> guard(
413         bkpt_sp->GetTarget().GetAPIMutex());
414     num_resolved = bkpt_sp->GetNumResolvedLocations();
415   }
416   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
417   LLDB_LOG(log, "breakpoint = {0}, num_resolved = {1}", bkpt_sp.get(),
418            num_resolved);
419   return num_resolved;
420 }
421
422 size_t SBBreakpoint::GetNumLocations() const {
423   BreakpointSP bkpt_sp = GetSP();
424   size_t num_locs = 0;
425   if (bkpt_sp) {
426     std::lock_guard<std::recursive_mutex> guard(
427         bkpt_sp->GetTarget().GetAPIMutex());
428     num_locs = bkpt_sp->GetNumLocations();
429   }
430   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
431   LLDB_LOG(log, "breakpoint = {0}, num_locs = {1}", bkpt_sp.get(), num_locs);
432   return num_locs;
433 }
434
435 void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) {
436   BreakpointSP bkpt_sp = GetSP();
437   if (!bkpt_sp)
438     return;
439   if (commands.GetSize() == 0)
440     return;
441
442   std::lock_guard<std::recursive_mutex> guard(
443       bkpt_sp->GetTarget().GetAPIMutex());
444   std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
445       new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
446
447   bkpt_sp->GetOptions()->SetCommandDataCallback(cmd_data_up);
448 }
449
450 bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) {
451   BreakpointSP bkpt_sp = GetSP();
452   if (!bkpt_sp)
453     return false;
454   StringList command_list;
455   bool has_commands =
456       bkpt_sp->GetOptions()->GetCommandLineCallbacks(command_list);
457   if (has_commands)
458     commands.AppendList(command_list);
459   return has_commands;
460 }
461
462 bool SBBreakpoint::GetDescription(SBStream &s) {
463   return GetDescription(s, true);
464 }
465
466 bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) {
467   BreakpointSP bkpt_sp = GetSP();
468   if (bkpt_sp) {
469     std::lock_guard<std::recursive_mutex> guard(
470         bkpt_sp->GetTarget().GetAPIMutex());
471     s.Printf("SBBreakpoint: id = %i, ", bkpt_sp->GetID());
472     bkpt_sp->GetResolverDescription(s.get());
473     bkpt_sp->GetFilterDescription(s.get());
474     if (include_locations) {
475       const size_t num_locations = bkpt_sp->GetNumLocations();
476       s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
477     }
478     return true;
479   }
480   s.Printf("No value");
481   return false;
482 }
483
484 bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton,
485                                                 StoppointCallbackContext *ctx,
486                                                 lldb::user_id_t break_id,
487                                                 lldb::user_id_t break_loc_id) {
488   ExecutionContext exe_ctx(ctx->exe_ctx_ref);
489   BreakpointSP bp_sp(
490       exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
491   if (baton && bp_sp) {
492     CallbackData *data = (CallbackData *)baton;
493     lldb_private::Breakpoint *bp = bp_sp.get();
494     if (bp && data->callback) {
495       Process *process = exe_ctx.GetProcessPtr();
496       if (process) {
497         SBProcess sb_process(process->shared_from_this());
498         SBThread sb_thread;
499         SBBreakpointLocation sb_location;
500         assert(bp_sp);
501         sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id));
502         Thread *thread = exe_ctx.GetThreadPtr();
503         if (thread)
504           sb_thread.SetThread(thread->shared_from_this());
505
506         return data->callback(data->callback_baton, sb_process, sb_thread,
507                               sb_location);
508       }
509     }
510   }
511   return true; // Return true if we should stop at this breakpoint
512 }
513
514 void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) {
515   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
516   BreakpointSP bkpt_sp = GetSP();
517   LLDB_LOG(log, "breakpoint = {0}, callback = {1}, baton = {2}", bkpt_sp.get(),
518            callback, baton);
519
520   if (bkpt_sp) {
521     std::lock_guard<std::recursive_mutex> guard(
522         bkpt_sp->GetTarget().GetAPIMutex());
523     BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));
524     bkpt_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback, baton_sp,
525                          false);
526   }
527 }
528
529 void SBBreakpoint::SetScriptCallbackFunction(
530     const char *callback_function_name) {
531   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
532   BreakpointSP bkpt_sp = GetSP();
533   LLDB_LOG(log, "breakpoint = {0}, callback = {1}", bkpt_sp.get(),
534            callback_function_name);
535
536   if (bkpt_sp) {
537     std::lock_guard<std::recursive_mutex> guard(
538         bkpt_sp->GetTarget().GetAPIMutex());
539     BreakpointOptions *bp_options = bkpt_sp->GetOptions();
540     bkpt_sp->GetTarget()
541         .GetDebugger()
542         .GetCommandInterpreter()
543         .GetScriptInterpreter()
544         ->SetBreakpointCommandCallbackFunction(bp_options,
545                                                callback_function_name);
546   }
547 }
548
549 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
550   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
551   BreakpointSP bkpt_sp = GetSP();
552   LLDB_LOG(log, "breakpoint = {0}, callback body:\n{1}", bkpt_sp.get(),
553            callback_body_text);
554
555   SBError sb_error;
556   if (bkpt_sp) {
557     std::lock_guard<std::recursive_mutex> guard(
558         bkpt_sp->GetTarget().GetAPIMutex());
559     BreakpointOptions *bp_options = bkpt_sp->GetOptions();
560     Status error =
561         bkpt_sp->GetTarget()
562             .GetDebugger()
563             .GetCommandInterpreter()
564             .GetScriptInterpreter()
565             ->SetBreakpointCommandCallback(bp_options, callback_body_text);
566     sb_error.SetError(error);
567   } else
568     sb_error.SetErrorString("invalid breakpoint");
569
570   return sb_error;
571 }
572
573 bool SBBreakpoint::AddName(const char *new_name) {
574   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
575   BreakpointSP bkpt_sp = GetSP();
576   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), new_name);
577
578   if (bkpt_sp) {
579     std::lock_guard<std::recursive_mutex> guard(
580         bkpt_sp->GetTarget().GetAPIMutex());
581     Status error; // Think I'm just going to swallow the error here, it's
582                   // probably more annoying to have to provide it.
583     return bkpt_sp->AddName(new_name, error);
584   }
585
586   return false;
587 }
588
589 void SBBreakpoint::RemoveName(const char *name_to_remove) {
590   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
591   BreakpointSP bkpt_sp = GetSP();
592   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name_to_remove);
593
594   if (bkpt_sp) {
595     std::lock_guard<std::recursive_mutex> guard(
596         bkpt_sp->GetTarget().GetAPIMutex());
597     bkpt_sp->RemoveName(name_to_remove);
598   }
599 }
600
601 bool SBBreakpoint::MatchesName(const char *name) {
602   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
603   BreakpointSP bkpt_sp = GetSP();
604   LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name);
605
606   if (bkpt_sp) {
607     std::lock_guard<std::recursive_mutex> guard(
608         bkpt_sp->GetTarget().GetAPIMutex());
609     return bkpt_sp->MatchesName(name);
610   }
611
612   return false;
613 }
614
615 void SBBreakpoint::GetNames(SBStringList &names) {
616   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
617   BreakpointSP bkpt_sp = GetSP();
618   LLDB_LOG(log, "breakpoint = {0}", bkpt_sp.get());
619
620   if (bkpt_sp) {
621     std::lock_guard<std::recursive_mutex> guard(
622         bkpt_sp->GetTarget().GetAPIMutex());
623     std::vector<std::string> names_vec;
624     bkpt_sp->GetNames(names_vec);
625     for (std::string name : names_vec) {
626       names.AppendString(name.c_str());
627     }
628   }
629 }
630
631 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) {
632   return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) !=
633          nullptr;
634 }
635
636 BreakpointEventType
637 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) {
638   if (event.IsValid())
639     return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
640         event.GetSP());
641   return eBreakpointEventTypeInvalidType;
642 }
643
644 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) {
645   if (event.IsValid())
646     return SBBreakpoint(
647         Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event.GetSP()));
648   return SBBreakpoint();
649 }
650
651 SBBreakpointLocation
652 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
653                                                     uint32_t loc_idx) {
654   SBBreakpointLocation sb_breakpoint_loc;
655   if (event.IsValid())
656     sb_breakpoint_loc.SetLocation(
657         Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
658             event.GetSP(), loc_idx));
659   return sb_breakpoint_loc;
660 }
661
662 uint32_t
663 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) {
664   uint32_t num_locations = 0;
665   if (event.IsValid())
666     num_locations =
667         (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
668             event.GetSP()));
669   return num_locations;
670 }
671
672 BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); }
673
674 // This is simple collection of breakpoint id's and their target.
675 class SBBreakpointListImpl {
676 public:
677   SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() {
678     if (target_sp && target_sp->IsValid())
679       m_target_wp = target_sp;
680   }
681
682   ~SBBreakpointListImpl() = default;
683
684   size_t GetSize() { return m_break_ids.size(); }
685
686   BreakpointSP GetBreakpointAtIndex(size_t idx) {
687     if (idx >= m_break_ids.size())
688       return BreakpointSP();
689     TargetSP target_sp = m_target_wp.lock();
690     if (!target_sp)
691       return BreakpointSP();
692     lldb::break_id_t bp_id = m_break_ids[idx];
693     return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
694   }
695
696   BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) {
697     TargetSP target_sp = m_target_wp.lock();
698     if (!target_sp)
699       return BreakpointSP();
700
701     for (lldb::break_id_t &break_id : m_break_ids) {
702       if (break_id == desired_id)
703         return target_sp->GetBreakpointList().FindBreakpointByID(break_id);
704     }
705     return BreakpointSP();
706   }
707
708   bool Append(BreakpointSP bkpt) {
709     TargetSP target_sp = m_target_wp.lock();
710     if (!target_sp || !bkpt)
711       return false;
712     if (bkpt->GetTargetSP() != target_sp)
713       return false;
714     m_break_ids.push_back(bkpt->GetID());
715     return true;
716   }
717
718   bool AppendIfUnique(BreakpointSP bkpt) {
719     TargetSP target_sp = m_target_wp.lock();
720     if (!target_sp || !bkpt)
721       return false;
722     if (bkpt->GetTargetSP() != target_sp)
723       return false;
724     lldb::break_id_t bp_id = bkpt->GetID();
725     if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) ==
726         m_break_ids.end())
727       return false;
728
729     m_break_ids.push_back(bkpt->GetID());
730     return true;
731   }
732
733   bool AppendByID(lldb::break_id_t id) {
734     TargetSP target_sp = m_target_wp.lock();
735     if (!target_sp)
736       return false;
737     if (id == LLDB_INVALID_BREAK_ID)
738       return false;
739     m_break_ids.push_back(id);
740     return true;
741   }
742
743   void Clear() { m_break_ids.clear(); }
744
745   void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) {
746     for (lldb::break_id_t id : m_break_ids) {
747       bp_list.AddBreakpointID(BreakpointID(id));
748     }
749   }
750
751   TargetSP GetTarget() { return m_target_wp.lock(); }
752
753 private:
754   std::vector<lldb::break_id_t> m_break_ids;
755   TargetWP m_target_wp;
756 };
757
758 SBBreakpointList::SBBreakpointList(SBTarget &target)
759     : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) {}
760
761 SBBreakpointList::~SBBreakpointList() {}
762
763 size_t SBBreakpointList::GetSize() const {
764   if (!m_opaque_sp)
765     return 0;
766   else
767     return m_opaque_sp->GetSize();
768 }
769
770 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
771   if (!m_opaque_sp)
772     return SBBreakpoint();
773
774   BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx);
775   return SBBreakpoint(bkpt_sp);
776 }
777
778 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) {
779   if (!m_opaque_sp)
780     return SBBreakpoint();
781   BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id);
782   return SBBreakpoint(bkpt_sp);
783 }
784
785 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
786   if (!sb_bkpt.IsValid())
787     return;
788   if (!m_opaque_sp)
789     return;
790   m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock());
791 }
792
793 void SBBreakpointList::AppendByID(lldb::break_id_t id) {
794   if (!m_opaque_sp)
795     return;
796   m_opaque_sp->AppendByID(id);
797 }
798
799 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) {
800   if (!sb_bkpt.IsValid())
801     return false;
802   if (!m_opaque_sp)
803     return false;
804   return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP());
805 }
806
807 void SBBreakpointList::Clear() {
808   if (m_opaque_sp)
809     m_opaque_sp->Clear();
810 }
811
812 void SBBreakpointList::CopyToBreakpointIDList(
813     lldb_private::BreakpointIDList &bp_id_list) {
814   if (m_opaque_sp)
815     m_opaque_sp->CopyToBreakpointIDList(bp_id_list);
816 }