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 "SBReproducerPrivate.h"
11#include "lldb/API/SBBreakpointLocation.h"
12#include "lldb/API/SBDebugger.h"
13#include "lldb/API/SBEvent.h"
14#include "lldb/API/SBProcess.h"
15#include "lldb/API/SBStream.h"
16#include "lldb/API/SBStringList.h"
17#include "lldb/API/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
45using namespace lldb;
46using namespace lldb_private;
47
48SBBreakpoint::SBBreakpoint() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBreakpoint); }
49
50SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs)
51 : m_opaque_wp(rhs.m_opaque_wp) {
52 LLDB_RECORD_CONSTRUCTOR(SBBreakpoint, (const lldb::SBBreakpoint &), rhs);
53}
54
55SBBreakpoint::SBBreakpoint(const lldb::BreakpointSP &bp_sp)
56 : m_opaque_wp(bp_sp) {
57 LLDB_RECORD_CONSTRUCTOR(SBBreakpoint, (const lldb::BreakpointSP &), bp_sp);
58}
59
60SBBreakpoint::~SBBreakpoint() = default;
61
62const 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 LLDB_RECORD_RESULT(*this);
68}
69
70bool 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
77bool 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
84SBTarget 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 LLDB_RECORD_RESULT(SBTarget(bkpt_sp->GetTargetSP()));
90
91 return LLDB_RECORD_RESULT(SBTarget());
92}
93
94break_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
105bool SBBreakpoint::IsValid() const {
106 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsValid);
107 return this->operator bool();
108}
109SBBreakpoint::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
121void 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
132SBBreakpointLocation 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 LLDB_RECORD_RESULT(sb_bp_location);
152}
153
154break_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
175SBBreakpointLocation 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 LLDB_RECORD_RESULT(sb_bp_location);
189}
190
191SBBreakpointLocation 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 LLDB_RECORD_RESULT(sb_bp_location);
205}
206
207void 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
219bool 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
231void 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
243bool 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
255bool 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
267void 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
279void 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
291const 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
303void 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
315bool 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
327uint32_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
341uint32_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
355void 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
366tid_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
380void 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
391uint32_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
408void 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
421const 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
438void 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
450const 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
467size_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
481size_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
494void 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
512bool 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
527bool SBBreakpoint::GetDescription(SBStream &s) {
528 LLDB_RECORD_METHOD(bool, SBBreakpoint, GetDescription, (lldb::SBStream &), s);
529
530 return GetDescription(s, true);
531}
532
533bool 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
554SBError 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 LLDB_RECORD_RESULT(error);
564 }
565
566 if (!bkpt_sp) {
567 error.SetErrorString("No breakpoint to add a location to.");
568 return LLDB_RECORD_RESULT(error);
569 }
570
571 if (!llvm::isa<BreakpointResolverScripted>(bkpt_sp->GetResolver().get())) {
572 error.SetErrorString("Only a scripted resolver can add locations.");
573 return LLDB_RECORD_RESULT(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 LLDB_RECORD_RESULT(error);
586}
587
588SBStructuredData 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 LLDB_RECORD_RESULT(data);
597
598 StructuredData::ObjectSP bkpt_dict = bkpt_sp->SerializeToStructuredData();
599 data.m_impl_up->SetObjectSP(bkpt_dict);
600 return LLDB_RECORD_RESULT(data);
601}
602
603void 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
619void SBBreakpoint::SetScriptCallbackFunction(
620 const char *callback_function_name) {
621LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
622 (const char *), callback_function_name);
623 SBStructuredData empty_args;
624 SetScriptCallbackFunction(callback_function_name, empty_args);
625}
626
627SBError 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 LLDB_RECORD_RESULT(sb_error);
652}
653
654SBError 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 LLDB_RECORD_RESULT(sb_error);
675}
676
677bool 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
684SBError 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 LLDB_RECORD_RESULT(status);
702}
703
704void 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
718bool 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
732void 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
749bool 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
757BreakpointEventType
758SBBreakpoint::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
769SBBreakpoint 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 LLDB_RECORD_RESULT(
776 SBBreakpoint(Breakpoint::BreakpointEventData::GetBreakpointFromEvent(
777 event.GetSP())));
778 return LLDB_RECORD_RESULT(SBBreakpoint());
779}
780
781SBBreakpointLocation
782SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
783 uint32_t loc_idx) {
784 LLDB_RECORD_STATIC_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
785 GetBreakpointLocationAtIndexFromEvent,
786 (const lldb::SBEvent &, uint32_t), event, loc_idx);
787
788 SBBreakpointLocation sb_breakpoint_loc;
789 if (event.IsValid())
790 sb_breakpoint_loc.SetLocation(
791 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
792 event.GetSP(), loc_idx));
793 return LLDB_RECORD_RESULT(sb_breakpoint_loc);
794}
795
796uint32_t
797SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) {
798 LLDB_RECORD_STATIC_METHOD(uint32_t, SBBreakpoint,
799 GetNumBreakpointLocationsFromEvent,
800 (const lldb::SBEvent &), event);
801
802 uint32_t num_locations = 0;
803 if (event.IsValid())
804 num_locations =
805 (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
806 event.GetSP()));
807 return num_locations;
808}
809
810bool SBBreakpoint::IsHardware() const {
811 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsHardware);
812
813 BreakpointSP bkpt_sp = GetSP();
814 if (bkpt_sp)
815 return bkpt_sp->IsHardware();
816 return false;
817}
818
819BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); }
820
821// This is simple collection of breakpoint id's and their target.
822class SBBreakpointListImpl {
823public:
824 SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() {
825 if (target_sp && target_sp->IsValid())
826 m_target_wp = target_sp;
827 }
828
829 ~SBBreakpointListImpl() = default;
830
831 size_t GetSize() { return m_break_ids.size(); }
832
833 BreakpointSP GetBreakpointAtIndex(size_t idx) {
834 if (idx >= m_break_ids.size())
835 return BreakpointSP();
836 TargetSP target_sp = m_target_wp.lock();
837 if (!target_sp)
838 return BreakpointSP();
839 lldb::break_id_t bp_id = m_break_ids[idx];
840 return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
841 }
842
843 BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) {
844 TargetSP target_sp = m_target_wp.lock();
845 if (!target_sp)
846 return BreakpointSP();
847
848 for (lldb::break_id_t &break_id : m_break_ids) {
849 if (break_id == desired_id)
850 return target_sp->GetBreakpointList().FindBreakpointByID(break_id);
851 }
852 return BreakpointSP();
853 }
854
855 bool Append(BreakpointSP bkpt) {
856 TargetSP target_sp = m_target_wp.lock();
857 if (!target_sp || !bkpt)
858 return false;
859 if (bkpt->GetTargetSP() != target_sp)
860 return false;
861 m_break_ids.push_back(bkpt->GetID());
862 return true;
863 }
864
865 bool AppendIfUnique(BreakpointSP bkpt) {
866 TargetSP target_sp = m_target_wp.lock();
867 if (!target_sp || !bkpt)
868 return false;
869 if (bkpt->GetTargetSP() != target_sp)
870 return false;
871 lldb::break_id_t bp_id = bkpt->GetID();
872 if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) ==
873 m_break_ids.end())
874 return false;
875
876 m_break_ids.push_back(bkpt->GetID());
877 return true;
878 }
879
880 bool AppendByID(lldb::break_id_t id) {
881 TargetSP target_sp = m_target_wp.lock();
882 if (!target_sp)
883 return false;
884 if (id == LLDB_INVALID_BREAK_ID)
885 return false;
886 m_break_ids.push_back(id);
887 return true;
888 }
889
890 void Clear() { m_break_ids.clear(); }
891
892 void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) {
893 for (lldb::break_id_t id : m_break_ids) {
894 bp_list.AddBreakpointID(BreakpointID(id));
895 }
896 }
897
898 TargetSP GetTarget() { return m_target_wp.lock(); }
899
900private:
901 std::vector<lldb::break_id_t> m_break_ids;
902 TargetWP m_target_wp;
903};
904
905SBBreakpointList::SBBreakpointList(SBTarget &target)
906 : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) {
907 LLDB_RECORD_CONSTRUCTOR(SBBreakpointList, (lldb::SBTarget &), target);
908}
909
910SBBreakpointList::~SBBreakpointList() = default;
911
912size_t SBBreakpointList::GetSize() const {
913 LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBBreakpointList, GetSize);
914
915 if (!m_opaque_sp)
916 return 0;
917 else
918 return m_opaque_sp->GetSize();
919}
920
921SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
922 LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, GetBreakpointAtIndex,
923 (size_t), idx);
924
925 if (!m_opaque_sp)
926 return LLDB_RECORD_RESULT(SBBreakpoint());
927
928 BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx);
929 return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp));
930}
931
932SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) {
933 LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, FindBreakpointByID,
934 (lldb::break_id_t), id);
935
936 if (!m_opaque_sp)
937 return LLDB_RECORD_RESULT(SBBreakpoint());
938 BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id);
939 return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp));
940}
941
942void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
943 LLDB_RECORD_METHOD(void, SBBreakpointList, Append,
944 (const lldb::SBBreakpoint &), sb_bkpt);
945
946 if (!sb_bkpt.IsValid())
947 return;
948 if (!m_opaque_sp)
949 return;
950 m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock());
951}
952
953void SBBreakpointList::AppendByID(lldb::break_id_t id) {
954 LLDB_RECORD_METHOD(void, SBBreakpointList, AppendByID, (lldb::break_id_t),
955 id);
956
957 if (!m_opaque_sp)
958 return;
959 m_opaque_sp->AppendByID(id);
960}
961
962bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) {
963 LLDB_RECORD_METHOD(bool, SBBreakpointList, AppendIfUnique,
964 (const lldb::SBBreakpoint &), sb_bkpt);
965
966 if (!sb_bkpt.IsValid())
967 return false;
968 if (!m_opaque_sp)
969 return false;
970 return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP());
971}
972
973void SBBreakpointList::Clear() {
974 LLDB_RECORD_METHOD_NO_ARGS(void, SBBreakpointList, Clear);
975
976 if (m_opaque_sp)
977 m_opaque_sp->Clear();
978}
979
980void SBBreakpointList::CopyToBreakpointIDList(
981 lldb_private::BreakpointIDList &bp_id_list) {
982 if (m_opaque_sp)
983 m_opaque_sp->CopyToBreakpointIDList(bp_id_list);
984}
985
986namespace lldb_private {
987namespace repro {
988
989template <>
990void RegisterMethods<SBBreakpoint>(Registry &R) {
991 LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, ());
992 LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, (const lldb::SBBreakpoint &));
993 LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, (const lldb::BreakpointSP &));
994 LLDB_REGISTER_METHOD(const lldb::SBBreakpoint &,
995 SBBreakpoint, operator=,(const lldb::SBBreakpoint &));
996 LLDB_REGISTER_METHOD(bool,
997 SBBreakpoint, operator==,(const lldb::SBBreakpoint &));
998 LLDB_REGISTER_METHOD(bool,
999 SBBreakpoint, operator!=,(const lldb::SBBreakpoint &));
1000 LLDB_REGISTER_METHOD_CONST(lldb::SBTarget, SBBreakpoint, GetTarget, ());
1001 LLDB_REGISTER_METHOD_CONST(lldb::break_id_t, SBBreakpoint, GetID, ());
1002 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsValid, ());
1003 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, operator bool, ());
1004 LLDB_REGISTER_METHOD(void, SBBreakpoint, ClearAllBreakpointSites, ());
1005 LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
1006 FindLocationByAddress, (lldb::addr_t));
1007 LLDB_REGISTER_METHOD(lldb::break_id_t, SBBreakpoint,
1008 FindLocationIDByAddress, (lldb::addr_t));
1009 LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
1010 FindLocationByID, (lldb::break_id_t));
1011 LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
1012 GetLocationAtIndex, (uint32_t));
1013 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetEnabled, (bool));
1014 LLDB_REGISTER_METHOD(bool, SBBreakpoint, IsEnabled, ());
1015 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetOneShot, (bool));
1016 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsOneShot, ());
1017 LLDB_REGISTER_METHOD(bool, SBBreakpoint, IsInternal, ());
1018 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetIgnoreCount, (uint32_t));
1019 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetCondition, (const char *));
1020 LLDB_REGISTER_METHOD(const char *, SBBreakpoint, GetCondition, ());
1021 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetAutoContinue, (bool));
1022 LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetAutoContinue, ());
1023 LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetHitCount, ());
1024 LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetIgnoreCount, ());
1025 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadID, (lldb::tid_t));
1026 LLDB_REGISTER_METHOD(lldb::tid_t, SBBreakpoint, GetThreadID, ());
1027 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadIndex, (uint32_t));
1028 LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetThreadIndex, ());
1029 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadName, (const char *));
1030 LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpoint, GetThreadName, ());
1031 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetQueueName, (const char *));
1032 LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpoint, GetQueueName, ());
1033 LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpoint, GetNumResolvedLocations,
1034 ());
1035 LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpoint, GetNumLocations, ());
1036 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetCommandLineCommands,
1037 (lldb::SBStringList &));
1038 LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetCommandLineCommands,
1039 (lldb::SBStringList &));
1040 LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetDescription,
1041 (lldb::SBStream &));
1042 LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetDescription,
1043 (lldb::SBStream &, bool));
1044 LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, AddLocation,
1045 (lldb::SBAddress &));
1046 LLDB_REGISTER_METHOD(lldb::SBStructuredData, SBBreakpoint,
1047 SerializeToStructuredData, ());
1048 LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallbackFunction,
1049 (const char *));
1050 LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackFunction,
1051 (const char *, SBStructuredData &));
1052 LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackBody,
1053 (const char *));
1054 LLDB_REGISTER_METHOD(bool, SBBreakpoint, AddName, (const char *));
1055 LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, AddNameWithErrorHandling,
1056 (const char *));
1057 LLDB_REGISTER_METHOD(void, SBBreakpoint, RemoveName, (const char *));
1058 LLDB_REGISTER_METHOD(bool, SBBreakpoint, MatchesName, (const char *));
1059 LLDB_REGISTER_METHOD(void, SBBreakpoint, GetNames, (lldb::SBStringList &));
1060 LLDB_REGISTER_STATIC_METHOD(bool, SBBreakpoint, EventIsBreakpointEvent,
1061 (const lldb::SBEvent &));
1062 LLDB_REGISTER_STATIC_METHOD(lldb::BreakpointEventType, SBBreakpoint,
1063 GetBreakpointEventTypeFromEvent,
1064 (const lldb::SBEvent &));
1065 LLDB_REGISTER_STATIC_METHOD(lldb::SBBreakpoint, SBBreakpoint,
1066 GetBreakpointFromEvent,
1067 (const lldb::SBEvent &));
1068 LLDB_REGISTER_STATIC_METHOD(lldb::SBBreakpointLocation, SBBreakpoint,
1069 GetBreakpointLocationAtIndexFromEvent,
1070 (const lldb::SBEvent &, uint32_t));
1071 LLDB_REGISTER_STATIC_METHOD(uint32_t, SBBreakpoint,
1072 GetNumBreakpointLocationsFromEvent,
1073 (const lldb::SBEvent &));
1074 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsHardware, ());
1075}
1076
1077template <>
1078void RegisterMethods<SBBreakpointList>(Registry &R) {
1079 LLDB_REGISTER_CONSTRUCTOR(SBBreakpointList, (lldb::SBTarget &));
1080 LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpointList, GetSize, ());
1081 LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointList,
1082 GetBreakpointAtIndex, (size_t));
1083 LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointList,
1084 FindBreakpointByID, (lldb::break_id_t));
1085 LLDB_REGISTER_METHOD(void, SBBreakpointList, Append,
1086 (const lldb::SBBreakpoint &));
1087 LLDB_REGISTER_METHOD(void, SBBreakpointList, AppendByID,
1088 (lldb::break_id_t));
1089 LLDB_REGISTER_METHOD(bool, SBBreakpointList, AppendIfUnique,
1090 (const lldb::SBBreakpoint &));
1091 LLDB_REGISTER_METHOD(void, SBBreakpointList, Clear, ());
1092}
1093
1094}
1095}
1096