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