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