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