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