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