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