1 //===-- SBBreakpointLocation.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/SBBreakpointLocation.h"
10 #include "lldb/API/SBAddress.h"
11 #include "lldb/API/SBDebugger.h"
12 #include "lldb/API/SBDefines.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/API/SBStringList.h"
15 #include "lldb/API/SBStructuredData.h"
16 #include "lldb/Utility/Instrumentation.h"
17
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/StreamFile.h"
22 #include "lldb/Core/StructuredDataImpl.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/ScriptInterpreter.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/ThreadSpec.h"
27 #include "lldb/Utility/Stream.h"
28 #include "lldb/lldb-defines.h"
29 #include "lldb/lldb-types.h"
30
31 using namespace lldb;
32 using namespace lldb_private;
33
SBBreakpointLocation()34 SBBreakpointLocation::SBBreakpointLocation() { LLDB_INSTRUMENT_VA(this); }
35
SBBreakpointLocation(const lldb::BreakpointLocationSP & break_loc_sp)36 SBBreakpointLocation::SBBreakpointLocation(
37 const lldb::BreakpointLocationSP &break_loc_sp)
38 : m_opaque_wp(break_loc_sp) {
39 LLDB_INSTRUMENT_VA(this, break_loc_sp);
40 }
41
SBBreakpointLocation(const SBBreakpointLocation & rhs)42 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs)
43 : m_opaque_wp(rhs.m_opaque_wp) {
44 LLDB_INSTRUMENT_VA(this, rhs);
45 }
46
47 const SBBreakpointLocation &SBBreakpointLocation::
operator =(const SBBreakpointLocation & rhs)48 operator=(const SBBreakpointLocation &rhs) {
49 LLDB_INSTRUMENT_VA(this, rhs);
50
51 m_opaque_wp = rhs.m_opaque_wp;
52 return *this;
53 }
54
55 SBBreakpointLocation::~SBBreakpointLocation() = default;
56
GetSP() const57 BreakpointLocationSP SBBreakpointLocation::GetSP() const {
58 return m_opaque_wp.lock();
59 }
60
IsValid() const61 bool SBBreakpointLocation::IsValid() const {
62 LLDB_INSTRUMENT_VA(this);
63 return this->operator bool();
64 }
operator bool() const65 SBBreakpointLocation::operator bool() const {
66 LLDB_INSTRUMENT_VA(this);
67
68 return bool(GetSP());
69 }
70
GetAddress()71 SBAddress SBBreakpointLocation::GetAddress() {
72 LLDB_INSTRUMENT_VA(this);
73
74 BreakpointLocationSP loc_sp = GetSP();
75 if (loc_sp) {
76 return SBAddress(loc_sp->GetAddress());
77 }
78
79 return SBAddress();
80 }
81
GetLoadAddress()82 addr_t SBBreakpointLocation::GetLoadAddress() {
83 LLDB_INSTRUMENT_VA(this);
84
85 addr_t ret_addr = LLDB_INVALID_ADDRESS;
86 BreakpointLocationSP loc_sp = GetSP();
87
88 if (loc_sp) {
89 std::lock_guard<std::recursive_mutex> guard(
90 loc_sp->GetTarget().GetAPIMutex());
91 ret_addr = loc_sp->GetLoadAddress();
92 }
93
94 return ret_addr;
95 }
96
SetEnabled(bool enabled)97 void SBBreakpointLocation::SetEnabled(bool enabled) {
98 LLDB_INSTRUMENT_VA(this, enabled);
99
100 BreakpointLocationSP loc_sp = GetSP();
101 if (loc_sp) {
102 std::lock_guard<std::recursive_mutex> guard(
103 loc_sp->GetTarget().GetAPIMutex());
104 loc_sp->SetEnabled(enabled);
105 }
106 }
107
IsEnabled()108 bool SBBreakpointLocation::IsEnabled() {
109 LLDB_INSTRUMENT_VA(this);
110
111 BreakpointLocationSP loc_sp = GetSP();
112 if (loc_sp) {
113 std::lock_guard<std::recursive_mutex> guard(
114 loc_sp->GetTarget().GetAPIMutex());
115 return loc_sp->IsEnabled();
116 } else
117 return false;
118 }
119
GetHitCount()120 uint32_t SBBreakpointLocation::GetHitCount() {
121 LLDB_INSTRUMENT_VA(this);
122
123 BreakpointLocationSP loc_sp = GetSP();
124 if (loc_sp) {
125 std::lock_guard<std::recursive_mutex> guard(
126 loc_sp->GetTarget().GetAPIMutex());
127 return loc_sp->GetHitCount();
128 } else
129 return 0;
130 }
131
GetIgnoreCount()132 uint32_t SBBreakpointLocation::GetIgnoreCount() {
133 LLDB_INSTRUMENT_VA(this);
134
135 BreakpointLocationSP loc_sp = GetSP();
136 if (loc_sp) {
137 std::lock_guard<std::recursive_mutex> guard(
138 loc_sp->GetTarget().GetAPIMutex());
139 return loc_sp->GetIgnoreCount();
140 } else
141 return 0;
142 }
143
SetIgnoreCount(uint32_t n)144 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) {
145 LLDB_INSTRUMENT_VA(this, n);
146
147 BreakpointLocationSP loc_sp = GetSP();
148 if (loc_sp) {
149 std::lock_guard<std::recursive_mutex> guard(
150 loc_sp->GetTarget().GetAPIMutex());
151 loc_sp->SetIgnoreCount(n);
152 }
153 }
154
SetCondition(const char * condition)155 void SBBreakpointLocation::SetCondition(const char *condition) {
156 LLDB_INSTRUMENT_VA(this, condition);
157
158 BreakpointLocationSP loc_sp = GetSP();
159 if (loc_sp) {
160 std::lock_guard<std::recursive_mutex> guard(
161 loc_sp->GetTarget().GetAPIMutex());
162 loc_sp->SetCondition(condition);
163 }
164 }
165
GetCondition()166 const char *SBBreakpointLocation::GetCondition() {
167 LLDB_INSTRUMENT_VA(this);
168
169 BreakpointLocationSP loc_sp = GetSP();
170 if (loc_sp) {
171 std::lock_guard<std::recursive_mutex> guard(
172 loc_sp->GetTarget().GetAPIMutex());
173 return loc_sp->GetConditionText();
174 }
175 return nullptr;
176 }
177
SetAutoContinue(bool auto_continue)178 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {
179 LLDB_INSTRUMENT_VA(this, auto_continue);
180
181 BreakpointLocationSP loc_sp = GetSP();
182 if (loc_sp) {
183 std::lock_guard<std::recursive_mutex> guard(
184 loc_sp->GetTarget().GetAPIMutex());
185 loc_sp->SetAutoContinue(auto_continue);
186 }
187 }
188
GetAutoContinue()189 bool SBBreakpointLocation::GetAutoContinue() {
190 LLDB_INSTRUMENT_VA(this);
191
192 BreakpointLocationSP loc_sp = GetSP();
193 if (loc_sp) {
194 std::lock_guard<std::recursive_mutex> guard(
195 loc_sp->GetTarget().GetAPIMutex());
196 return loc_sp->IsAutoContinue();
197 }
198 return false;
199 }
200
SetScriptCallbackFunction(const char * callback_function_name)201 void SBBreakpointLocation::SetScriptCallbackFunction(
202 const char *callback_function_name) {
203 LLDB_INSTRUMENT_VA(this, callback_function_name);
204 }
205
SetScriptCallbackFunction(const char * callback_function_name,SBStructuredData & extra_args)206 SBError SBBreakpointLocation::SetScriptCallbackFunction(
207 const char *callback_function_name,
208 SBStructuredData &extra_args) {
209 LLDB_INSTRUMENT_VA(this, callback_function_name, extra_args);
210 SBError sb_error;
211 BreakpointLocationSP loc_sp = GetSP();
212
213 if (loc_sp) {
214 Status error;
215 std::lock_guard<std::recursive_mutex> guard(
216 loc_sp->GetTarget().GetAPIMutex());
217 BreakpointOptions &bp_options = loc_sp->GetLocationOptions();
218 error = loc_sp->GetBreakpoint()
219 .GetTarget()
220 .GetDebugger()
221 .GetScriptInterpreter()
222 ->SetBreakpointCommandCallbackFunction(bp_options,
223 callback_function_name,
224 extra_args.m_impl_up
225 ->GetObjectSP());
226 sb_error.SetError(error);
227 } else
228 sb_error.SetErrorString("invalid breakpoint");
229
230 return sb_error;
231 }
232
233 SBError
SetScriptCallbackBody(const char * callback_body_text)234 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
235 LLDB_INSTRUMENT_VA(this, callback_body_text);
236
237 BreakpointLocationSP loc_sp = GetSP();
238
239 SBError sb_error;
240 if (loc_sp) {
241 std::lock_guard<std::recursive_mutex> guard(
242 loc_sp->GetTarget().GetAPIMutex());
243 BreakpointOptions &bp_options = loc_sp->GetLocationOptions();
244 Status error =
245 loc_sp->GetBreakpoint()
246 .GetTarget()
247 .GetDebugger()
248 .GetScriptInterpreter()
249 ->SetBreakpointCommandCallback(bp_options, callback_body_text);
250 sb_error.SetError(error);
251 } else
252 sb_error.SetErrorString("invalid breakpoint");
253
254 return sb_error;
255 }
256
SetCommandLineCommands(SBStringList & commands)257 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) {
258 LLDB_INSTRUMENT_VA(this, commands);
259
260 BreakpointLocationSP loc_sp = GetSP();
261 if (!loc_sp)
262 return;
263 if (commands.GetSize() == 0)
264 return;
265
266 std::lock_guard<std::recursive_mutex> guard(
267 loc_sp->GetTarget().GetAPIMutex());
268 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
269 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
270
271 loc_sp->GetLocationOptions().SetCommandDataCallback(cmd_data_up);
272 }
273
GetCommandLineCommands(SBStringList & commands)274 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) {
275 LLDB_INSTRUMENT_VA(this, commands);
276
277 BreakpointLocationSP loc_sp = GetSP();
278 if (!loc_sp)
279 return false;
280 StringList command_list;
281 bool has_commands =
282 loc_sp->GetLocationOptions().GetCommandLineCallbacks(command_list);
283 if (has_commands)
284 commands.AppendList(command_list);
285 return has_commands;
286 }
287
SetThreadID(tid_t thread_id)288 void SBBreakpointLocation::SetThreadID(tid_t thread_id) {
289 LLDB_INSTRUMENT_VA(this, thread_id);
290
291 BreakpointLocationSP loc_sp = GetSP();
292 if (loc_sp) {
293 std::lock_guard<std::recursive_mutex> guard(
294 loc_sp->GetTarget().GetAPIMutex());
295 loc_sp->SetThreadID(thread_id);
296 }
297 }
298
GetThreadID()299 tid_t SBBreakpointLocation::GetThreadID() {
300 LLDB_INSTRUMENT_VA(this);
301
302 tid_t tid = LLDB_INVALID_THREAD_ID;
303 BreakpointLocationSP loc_sp = GetSP();
304 if (loc_sp) {
305 std::lock_guard<std::recursive_mutex> guard(
306 loc_sp->GetTarget().GetAPIMutex());
307 return loc_sp->GetThreadID();
308 }
309 return tid;
310 }
311
SetThreadIndex(uint32_t index)312 void SBBreakpointLocation::SetThreadIndex(uint32_t index) {
313 LLDB_INSTRUMENT_VA(this, index);
314
315 BreakpointLocationSP loc_sp = GetSP();
316 if (loc_sp) {
317 std::lock_guard<std::recursive_mutex> guard(
318 loc_sp->GetTarget().GetAPIMutex());
319 loc_sp->SetThreadIndex(index);
320 }
321 }
322
GetThreadIndex() const323 uint32_t SBBreakpointLocation::GetThreadIndex() const {
324 LLDB_INSTRUMENT_VA(this);
325
326 uint32_t thread_idx = UINT32_MAX;
327 BreakpointLocationSP loc_sp = GetSP();
328 if (loc_sp) {
329 std::lock_guard<std::recursive_mutex> guard(
330 loc_sp->GetTarget().GetAPIMutex());
331 return loc_sp->GetThreadIndex();
332 }
333 return thread_idx;
334 }
335
SetThreadName(const char * thread_name)336 void SBBreakpointLocation::SetThreadName(const char *thread_name) {
337 LLDB_INSTRUMENT_VA(this, thread_name);
338
339 BreakpointLocationSP loc_sp = GetSP();
340 if (loc_sp) {
341 std::lock_guard<std::recursive_mutex> guard(
342 loc_sp->GetTarget().GetAPIMutex());
343 loc_sp->SetThreadName(thread_name);
344 }
345 }
346
GetThreadName() const347 const char *SBBreakpointLocation::GetThreadName() const {
348 LLDB_INSTRUMENT_VA(this);
349
350 BreakpointLocationSP loc_sp = GetSP();
351 if (loc_sp) {
352 std::lock_guard<std::recursive_mutex> guard(
353 loc_sp->GetTarget().GetAPIMutex());
354 return loc_sp->GetThreadName();
355 }
356 return nullptr;
357 }
358
SetQueueName(const char * queue_name)359 void SBBreakpointLocation::SetQueueName(const char *queue_name) {
360 LLDB_INSTRUMENT_VA(this, queue_name);
361
362 BreakpointLocationSP loc_sp = GetSP();
363 if (loc_sp) {
364 std::lock_guard<std::recursive_mutex> guard(
365 loc_sp->GetTarget().GetAPIMutex());
366 loc_sp->SetQueueName(queue_name);
367 }
368 }
369
GetQueueName() const370 const char *SBBreakpointLocation::GetQueueName() const {
371 LLDB_INSTRUMENT_VA(this);
372
373 BreakpointLocationSP loc_sp = GetSP();
374 if (loc_sp) {
375 std::lock_guard<std::recursive_mutex> guard(
376 loc_sp->GetTarget().GetAPIMutex());
377 loc_sp->GetQueueName();
378 }
379 return nullptr;
380 }
381
IsResolved()382 bool SBBreakpointLocation::IsResolved() {
383 LLDB_INSTRUMENT_VA(this);
384
385 BreakpointLocationSP loc_sp = GetSP();
386 if (loc_sp) {
387 std::lock_guard<std::recursive_mutex> guard(
388 loc_sp->GetTarget().GetAPIMutex());
389 return loc_sp->IsResolved();
390 }
391 return false;
392 }
393
SetLocation(const lldb::BreakpointLocationSP & break_loc_sp)394 void SBBreakpointLocation::SetLocation(
395 const lldb::BreakpointLocationSP &break_loc_sp) {
396 // Uninstall the callbacks?
397 m_opaque_wp = break_loc_sp;
398 }
399
GetDescription(SBStream & description,DescriptionLevel level)400 bool SBBreakpointLocation::GetDescription(SBStream &description,
401 DescriptionLevel level) {
402 LLDB_INSTRUMENT_VA(this, description, level);
403
404 Stream &strm = description.ref();
405 BreakpointLocationSP loc_sp = GetSP();
406
407 if (loc_sp) {
408 std::lock_guard<std::recursive_mutex> guard(
409 loc_sp->GetTarget().GetAPIMutex());
410 loc_sp->GetDescription(&strm, level);
411 strm.EOL();
412 } else
413 strm.PutCString("No value");
414
415 return true;
416 }
417
GetID()418 break_id_t SBBreakpointLocation::GetID() {
419 LLDB_INSTRUMENT_VA(this);
420
421 BreakpointLocationSP loc_sp = GetSP();
422 if (loc_sp) {
423 std::lock_guard<std::recursive_mutex> guard(
424 loc_sp->GetTarget().GetAPIMutex());
425 return loc_sp->GetID();
426 } else
427 return LLDB_INVALID_BREAK_ID;
428 }
429
GetBreakpoint()430 SBBreakpoint SBBreakpointLocation::GetBreakpoint() {
431 LLDB_INSTRUMENT_VA(this);
432
433 BreakpointLocationSP loc_sp = GetSP();
434
435 SBBreakpoint sb_bp;
436 if (loc_sp) {
437 std::lock_guard<std::recursive_mutex> guard(
438 loc_sp->GetTarget().GetAPIMutex());
439 sb_bp = loc_sp->GetBreakpoint().shared_from_this();
440 }
441
442 return sb_bp;
443 }
444