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