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