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