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 "SBReproducerPrivate.h"
11 #include "lldb/API/SBAddress.h"
12 #include "lldb/API/SBDebugger.h"
13 #include "lldb/API/SBDefines.h"
14 #include "lldb/API/SBStream.h"
15 #include "lldb/API/SBStructuredData.h"
16 #include "lldb/API/SBStringList.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 
34 SBBreakpointLocation::SBBreakpointLocation() {
35   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBreakpointLocation);
36 }
37 
38 SBBreakpointLocation::SBBreakpointLocation(
39     const lldb::BreakpointLocationSP &break_loc_sp)
40     : m_opaque_wp(break_loc_sp) {
41   LLDB_RECORD_CONSTRUCTOR(SBBreakpointLocation,
42                           (const lldb::BreakpointLocationSP &), break_loc_sp);
43 }
44 
45 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs)
46     : m_opaque_wp(rhs.m_opaque_wp) {
47   LLDB_RECORD_CONSTRUCTOR(SBBreakpointLocation,
48                           (const lldb::SBBreakpointLocation &), rhs);
49 }
50 
51 const SBBreakpointLocation &SBBreakpointLocation::
52 operator=(const SBBreakpointLocation &rhs) {
53   LLDB_RECORD_METHOD(
54       const lldb::SBBreakpointLocation &,
55       SBBreakpointLocation, operator=,(const lldb::SBBreakpointLocation &),
56       rhs);
57 
58   m_opaque_wp = rhs.m_opaque_wp;
59   return LLDB_RECORD_RESULT(*this);
60 }
61 
62 SBBreakpointLocation::~SBBreakpointLocation() = default;
63 
64 BreakpointLocationSP SBBreakpointLocation::GetSP() const {
65   return m_opaque_wp.lock();
66 }
67 
68 bool SBBreakpointLocation::IsValid() const {
69   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpointLocation, IsValid);
70   return this->operator bool();
71 }
72 SBBreakpointLocation::operator bool() const {
73   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpointLocation, operator bool);
74 
75   return bool(GetSP());
76 }
77 
78 SBAddress SBBreakpointLocation::GetAddress() {
79   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBBreakpointLocation, GetAddress);
80 
81   BreakpointLocationSP loc_sp = GetSP();
82   if (loc_sp) {
83     return LLDB_RECORD_RESULT(SBAddress(&loc_sp->GetAddress()));
84   }
85 
86   return LLDB_RECORD_RESULT(SBAddress());
87 }
88 
89 addr_t SBBreakpointLocation::GetLoadAddress() {
90   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBBreakpointLocation,
91                              GetLoadAddress);
92 
93   addr_t ret_addr = LLDB_INVALID_ADDRESS;
94   BreakpointLocationSP loc_sp = GetSP();
95 
96   if (loc_sp) {
97     std::lock_guard<std::recursive_mutex> guard(
98         loc_sp->GetTarget().GetAPIMutex());
99     ret_addr = loc_sp->GetLoadAddress();
100   }
101 
102   return ret_addr;
103 }
104 
105 void SBBreakpointLocation::SetEnabled(bool enabled) {
106   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetEnabled, (bool), enabled);
107 
108   BreakpointLocationSP loc_sp = GetSP();
109   if (loc_sp) {
110     std::lock_guard<std::recursive_mutex> guard(
111         loc_sp->GetTarget().GetAPIMutex());
112     loc_sp->SetEnabled(enabled);
113   }
114 }
115 
116 bool SBBreakpointLocation::IsEnabled() {
117   LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, IsEnabled);
118 
119   BreakpointLocationSP loc_sp = GetSP();
120   if (loc_sp) {
121     std::lock_guard<std::recursive_mutex> guard(
122         loc_sp->GetTarget().GetAPIMutex());
123     return loc_sp->IsEnabled();
124   } else
125     return false;
126 }
127 
128 uint32_t SBBreakpointLocation::GetHitCount() {
129   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBBreakpointLocation, GetHitCount);
130 
131   BreakpointLocationSP loc_sp = GetSP();
132   if (loc_sp) {
133     std::lock_guard<std::recursive_mutex> guard(
134         loc_sp->GetTarget().GetAPIMutex());
135     return loc_sp->GetHitCount();
136   } else
137     return 0;
138 }
139 
140 uint32_t SBBreakpointLocation::GetIgnoreCount() {
141   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBBreakpointLocation, GetIgnoreCount);
142 
143   BreakpointLocationSP loc_sp = GetSP();
144   if (loc_sp) {
145     std::lock_guard<std::recursive_mutex> guard(
146         loc_sp->GetTarget().GetAPIMutex());
147     return loc_sp->GetIgnoreCount();
148   } else
149     return 0;
150 }
151 
152 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) {
153   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetIgnoreCount, (uint32_t), n);
154 
155   BreakpointLocationSP loc_sp = GetSP();
156   if (loc_sp) {
157     std::lock_guard<std::recursive_mutex> guard(
158         loc_sp->GetTarget().GetAPIMutex());
159     loc_sp->SetIgnoreCount(n);
160   }
161 }
162 
163 void SBBreakpointLocation::SetCondition(const char *condition) {
164   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetCondition, (const char *),
165                      condition);
166 
167   BreakpointLocationSP loc_sp = GetSP();
168   if (loc_sp) {
169     std::lock_guard<std::recursive_mutex> guard(
170         loc_sp->GetTarget().GetAPIMutex());
171     loc_sp->SetCondition(condition);
172   }
173 }
174 
175 const char *SBBreakpointLocation::GetCondition() {
176   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBBreakpointLocation, GetCondition);
177 
178   BreakpointLocationSP loc_sp = GetSP();
179   if (loc_sp) {
180     std::lock_guard<std::recursive_mutex> guard(
181         loc_sp->GetTarget().GetAPIMutex());
182     return loc_sp->GetConditionText();
183   }
184   return nullptr;
185 }
186 
187 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {
188   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetAutoContinue, (bool),
189                      auto_continue);
190 
191   BreakpointLocationSP loc_sp = GetSP();
192   if (loc_sp) {
193     std::lock_guard<std::recursive_mutex> guard(
194         loc_sp->GetTarget().GetAPIMutex());
195     loc_sp->SetAutoContinue(auto_continue);
196   }
197 }
198 
199 bool SBBreakpointLocation::GetAutoContinue() {
200   LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, GetAutoContinue);
201 
202   BreakpointLocationSP loc_sp = GetSP();
203   if (loc_sp) {
204     std::lock_guard<std::recursive_mutex> guard(
205         loc_sp->GetTarget().GetAPIMutex());
206     return loc_sp->IsAutoContinue();
207   }
208   return false;
209 }
210 
211 void SBBreakpointLocation::SetScriptCallbackFunction(
212   const char *callback_function_name) {
213 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
214                    (const char *), callback_function_name);
215 }
216 
217 SBError SBBreakpointLocation::SetScriptCallbackFunction(
218     const char *callback_function_name,
219     SBStructuredData &extra_args) {
220   LLDB_RECORD_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction,
221                      (const char *, SBStructuredData &),
222                      callback_function_name, extra_args);
223   SBError sb_error;
224   BreakpointLocationSP loc_sp = GetSP();
225 
226   if (loc_sp) {
227     Status error;
228     std::lock_guard<std::recursive_mutex> guard(
229         loc_sp->GetTarget().GetAPIMutex());
230     BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
231     error = loc_sp->GetBreakpoint()
232         .GetTarget()
233         .GetDebugger()
234         .GetScriptInterpreter()
235         ->SetBreakpointCommandCallbackFunction(bp_options,
236                                                callback_function_name,
237                                                extra_args.m_impl_up
238                                                    ->GetObjectSP());
239       sb_error.SetError(error);
240     } else
241       sb_error.SetErrorString("invalid breakpoint");
242 
243     return LLDB_RECORD_RESULT(sb_error);
244 }
245 
246 SBError
247 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
248   LLDB_RECORD_METHOD(lldb::SBError, SBBreakpointLocation, SetScriptCallbackBody,
249                      (const char *), callback_body_text);
250 
251   BreakpointLocationSP loc_sp = GetSP();
252 
253   SBError sb_error;
254   if (loc_sp) {
255     std::lock_guard<std::recursive_mutex> guard(
256         loc_sp->GetTarget().GetAPIMutex());
257     BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
258     Status error =
259         loc_sp->GetBreakpoint()
260             .GetTarget()
261             .GetDebugger()
262             .GetScriptInterpreter()
263             ->SetBreakpointCommandCallback(bp_options, callback_body_text);
264     sb_error.SetError(error);
265   } else
266     sb_error.SetErrorString("invalid breakpoint");
267 
268   return LLDB_RECORD_RESULT(sb_error);
269 }
270 
271 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) {
272   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetCommandLineCommands,
273                      (lldb::SBStringList &), commands);
274 
275   BreakpointLocationSP loc_sp = GetSP();
276   if (!loc_sp)
277     return;
278   if (commands.GetSize() == 0)
279     return;
280 
281   std::lock_guard<std::recursive_mutex> guard(
282       loc_sp->GetTarget().GetAPIMutex());
283   std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(
284       new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));
285 
286   loc_sp->GetLocationOptions()->SetCommandDataCallback(cmd_data_up);
287 }
288 
289 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) {
290   LLDB_RECORD_METHOD(bool, SBBreakpointLocation, GetCommandLineCommands,
291                      (lldb::SBStringList &), commands);
292 
293   BreakpointLocationSP loc_sp = GetSP();
294   if (!loc_sp)
295     return false;
296   StringList command_list;
297   bool has_commands =
298       loc_sp->GetLocationOptions()->GetCommandLineCallbacks(command_list);
299   if (has_commands)
300     commands.AppendList(command_list);
301   return has_commands;
302 }
303 
304 void SBBreakpointLocation::SetThreadID(tid_t thread_id) {
305   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetThreadID, (lldb::tid_t),
306                      thread_id);
307 
308   BreakpointLocationSP loc_sp = GetSP();
309   if (loc_sp) {
310     std::lock_guard<std::recursive_mutex> guard(
311         loc_sp->GetTarget().GetAPIMutex());
312     loc_sp->SetThreadID(thread_id);
313   }
314 }
315 
316 tid_t SBBreakpointLocation::GetThreadID() {
317   LLDB_RECORD_METHOD_NO_ARGS(lldb::tid_t, SBBreakpointLocation, GetThreadID);
318 
319   tid_t tid = LLDB_INVALID_THREAD_ID;
320   BreakpointLocationSP loc_sp = GetSP();
321   if (loc_sp) {
322     std::lock_guard<std::recursive_mutex> guard(
323         loc_sp->GetTarget().GetAPIMutex());
324     return loc_sp->GetThreadID();
325   }
326   return tid;
327 }
328 
329 void SBBreakpointLocation::SetThreadIndex(uint32_t index) {
330   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetThreadIndex, (uint32_t),
331                      index);
332 
333   BreakpointLocationSP loc_sp = GetSP();
334   if (loc_sp) {
335     std::lock_guard<std::recursive_mutex> guard(
336         loc_sp->GetTarget().GetAPIMutex());
337     loc_sp->SetThreadIndex(index);
338   }
339 }
340 
341 uint32_t SBBreakpointLocation::GetThreadIndex() const {
342   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpointLocation,
343                                    GetThreadIndex);
344 
345   uint32_t thread_idx = UINT32_MAX;
346   BreakpointLocationSP loc_sp = GetSP();
347   if (loc_sp) {
348     std::lock_guard<std::recursive_mutex> guard(
349         loc_sp->GetTarget().GetAPIMutex());
350     return loc_sp->GetThreadIndex();
351   }
352   return thread_idx;
353 }
354 
355 void SBBreakpointLocation::SetThreadName(const char *thread_name) {
356   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetThreadName, (const char *),
357                      thread_name);
358 
359   BreakpointLocationSP loc_sp = GetSP();
360   if (loc_sp) {
361     std::lock_guard<std::recursive_mutex> guard(
362         loc_sp->GetTarget().GetAPIMutex());
363     loc_sp->SetThreadName(thread_name);
364   }
365 }
366 
367 const char *SBBreakpointLocation::GetThreadName() const {
368   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpointLocation,
369                                    GetThreadName);
370 
371   BreakpointLocationSP loc_sp = GetSP();
372   if (loc_sp) {
373     std::lock_guard<std::recursive_mutex> guard(
374         loc_sp->GetTarget().GetAPIMutex());
375     return loc_sp->GetThreadName();
376   }
377   return nullptr;
378 }
379 
380 void SBBreakpointLocation::SetQueueName(const char *queue_name) {
381   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetQueueName, (const char *),
382                      queue_name);
383 
384   BreakpointLocationSP loc_sp = GetSP();
385   if (loc_sp) {
386     std::lock_guard<std::recursive_mutex> guard(
387         loc_sp->GetTarget().GetAPIMutex());
388     loc_sp->SetQueueName(queue_name);
389   }
390 }
391 
392 const char *SBBreakpointLocation::GetQueueName() const {
393   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpointLocation,
394                                    GetQueueName);
395 
396   BreakpointLocationSP loc_sp = GetSP();
397   if (loc_sp) {
398     std::lock_guard<std::recursive_mutex> guard(
399         loc_sp->GetTarget().GetAPIMutex());
400     loc_sp->GetQueueName();
401   }
402   return nullptr;
403 }
404 
405 bool SBBreakpointLocation::IsResolved() {
406   LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, IsResolved);
407 
408   BreakpointLocationSP loc_sp = GetSP();
409   if (loc_sp) {
410     std::lock_guard<std::recursive_mutex> guard(
411         loc_sp->GetTarget().GetAPIMutex());
412     return loc_sp->IsResolved();
413   }
414   return false;
415 }
416 
417 void SBBreakpointLocation::SetLocation(
418     const lldb::BreakpointLocationSP &break_loc_sp) {
419   // Uninstall the callbacks?
420   m_opaque_wp = break_loc_sp;
421 }
422 
423 bool SBBreakpointLocation::GetDescription(SBStream &description,
424                                           DescriptionLevel level) {
425   LLDB_RECORD_METHOD(bool, SBBreakpointLocation, GetDescription,
426                      (lldb::SBStream &, lldb::DescriptionLevel), description,
427                      level);
428 
429   Stream &strm = description.ref();
430   BreakpointLocationSP loc_sp = GetSP();
431 
432   if (loc_sp) {
433     std::lock_guard<std::recursive_mutex> guard(
434         loc_sp->GetTarget().GetAPIMutex());
435     loc_sp->GetDescription(&strm, level);
436     strm.EOL();
437   } else
438     strm.PutCString("No value");
439 
440   return true;
441 }
442 
443 break_id_t SBBreakpointLocation::GetID() {
444   LLDB_RECORD_METHOD_NO_ARGS(lldb::break_id_t, SBBreakpointLocation, GetID);
445 
446   BreakpointLocationSP loc_sp = GetSP();
447   if (loc_sp) {
448     std::lock_guard<std::recursive_mutex> guard(
449         loc_sp->GetTarget().GetAPIMutex());
450     return loc_sp->GetID();
451   } else
452     return LLDB_INVALID_BREAK_ID;
453 }
454 
455 SBBreakpoint SBBreakpointLocation::GetBreakpoint() {
456   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBreakpoint, SBBreakpointLocation,
457                              GetBreakpoint);
458 
459   BreakpointLocationSP loc_sp = GetSP();
460 
461   SBBreakpoint sb_bp;
462   if (loc_sp) {
463     std::lock_guard<std::recursive_mutex> guard(
464         loc_sp->GetTarget().GetAPIMutex());
465     sb_bp = loc_sp->GetBreakpoint().shared_from_this();
466   }
467 
468   return LLDB_RECORD_RESULT(sb_bp);
469 }
470 
471 namespace lldb_private {
472 namespace repro {
473 
474 template <>
475 void RegisterMethods<SBBreakpointLocation>(Registry &R) {
476   LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation, ());
477   LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation,
478                             (const lldb::BreakpointLocationSP &));
479   LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation,
480                             (const lldb::SBBreakpointLocation &));
481   LLDB_REGISTER_METHOD(
482       const lldb::SBBreakpointLocation &,
483       SBBreakpointLocation, operator=,(const lldb::SBBreakpointLocation &));
484   LLDB_REGISTER_METHOD_CONST(bool, SBBreakpointLocation, IsValid, ());
485   LLDB_REGISTER_METHOD_CONST(bool, SBBreakpointLocation, operator bool, ());
486   LLDB_REGISTER_METHOD(lldb::SBAddress, SBBreakpointLocation, GetAddress, ());
487   LLDB_REGISTER_METHOD(lldb::addr_t, SBBreakpointLocation, GetLoadAddress,
488                        ());
489   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetEnabled, (bool));
490   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, IsEnabled, ());
491   LLDB_REGISTER_METHOD(uint32_t, SBBreakpointLocation, GetHitCount, ());
492   LLDB_REGISTER_METHOD(uint32_t, SBBreakpointLocation, GetIgnoreCount, ());
493   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetIgnoreCount,
494                        (uint32_t));
495   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetCondition,
496                        (const char *));
497   LLDB_REGISTER_METHOD(const char *, SBBreakpointLocation, GetCondition, ());
498   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetAutoContinue, (bool));
499   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetAutoContinue, ());
500   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
501                        (const char *));
502   LLDB_REGISTER_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction,
503                        (const char *, SBStructuredData &));
504   LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpointLocation,
505                        SetScriptCallbackBody, (const char *));
506   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetCommandLineCommands,
507                        (lldb::SBStringList &));
508   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetCommandLineCommands,
509                        (lldb::SBStringList &));
510   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadID,
511                        (lldb::tid_t));
512   LLDB_REGISTER_METHOD(lldb::tid_t, SBBreakpointLocation, GetThreadID, ());
513   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadIndex,
514                        (uint32_t));
515   LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpointLocation, GetThreadIndex,
516                              ());
517   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadName,
518                        (const char *));
519   LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpointLocation,
520                              GetThreadName, ());
521   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetQueueName,
522                        (const char *));
523   LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpointLocation, GetQueueName,
524                              ());
525   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, IsResolved, ());
526   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetDescription,
527                        (lldb::SBStream &, lldb::DescriptionLevel));
528   LLDB_REGISTER_METHOD(lldb::break_id_t, SBBreakpointLocation, GetID, ());
529   LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointLocation,
530                        GetBreakpoint, ());
531 }
532 
533 }
534 }
535