1 //===-- SBBreakpointLocation.cpp --------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/API/SBBreakpointLocation.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 
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::SetScriptCallbackFunction(
152     const char *callback_function_name) {
153   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
154   BreakpointLocationSP loc_sp = GetSP();
155   LLDB_LOG(log, "location = {0}, callback = {1}", loc_sp.get(),
156            callback_function_name);
157 
158   if (loc_sp) {
159     std::lock_guard<std::recursive_mutex> guard(
160         loc_sp->GetTarget().GetAPIMutex());
161     BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
162     loc_sp->GetBreakpoint()
163         .GetTarget()
164         .GetDebugger()
165         .GetCommandInterpreter()
166         .GetScriptInterpreter()
167         ->SetBreakpointCommandCallbackFunction(bp_options,
168                                                callback_function_name);
169   }
170 }
171 
172 SBError
173 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
174   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
175   BreakpointLocationSP loc_sp = GetSP();
176   LLDB_LOG(log, "location = {0}: callback body:\n{1}", loc_sp.get(),
177            callback_body_text);
178 
179   SBError sb_error;
180   if (loc_sp) {
181     std::lock_guard<std::recursive_mutex> guard(
182         loc_sp->GetTarget().GetAPIMutex());
183     BreakpointOptions *bp_options = loc_sp->GetLocationOptions();
184     Status error =
185         loc_sp->GetBreakpoint()
186             .GetTarget()
187             .GetDebugger()
188             .GetCommandInterpreter()
189             .GetScriptInterpreter()
190             ->SetBreakpointCommandCallback(bp_options, callback_body_text);
191     sb_error.SetError(error);
192   } else
193     sb_error.SetErrorString("invalid breakpoint");
194 
195   return sb_error;
196 }
197 
198 void SBBreakpointLocation::SetThreadID(tid_t thread_id) {
199   BreakpointLocationSP loc_sp = GetSP();
200   if (loc_sp) {
201     std::lock_guard<std::recursive_mutex> guard(
202         loc_sp->GetTarget().GetAPIMutex());
203     loc_sp->SetThreadID(thread_id);
204   }
205 }
206 
207 tid_t SBBreakpointLocation::GetThreadID() {
208   tid_t tid = LLDB_INVALID_THREAD_ID;
209   BreakpointLocationSP loc_sp = GetSP();
210   if (loc_sp) {
211     std::lock_guard<std::recursive_mutex> guard(
212         loc_sp->GetTarget().GetAPIMutex());
213     return loc_sp->GetThreadID();
214   }
215   return tid;
216 }
217 
218 void SBBreakpointLocation::SetThreadIndex(uint32_t index) {
219   BreakpointLocationSP loc_sp = GetSP();
220   if (loc_sp) {
221     std::lock_guard<std::recursive_mutex> guard(
222         loc_sp->GetTarget().GetAPIMutex());
223     loc_sp->SetThreadIndex(index);
224   }
225 }
226 
227 uint32_t SBBreakpointLocation::GetThreadIndex() const {
228   uint32_t thread_idx = UINT32_MAX;
229   BreakpointLocationSP loc_sp = GetSP();
230   if (loc_sp) {
231     std::lock_guard<std::recursive_mutex> guard(
232         loc_sp->GetTarget().GetAPIMutex());
233     return loc_sp->GetThreadIndex();
234   }
235   return thread_idx;
236 }
237 
238 void SBBreakpointLocation::SetThreadName(const char *thread_name) {
239   BreakpointLocationSP loc_sp = GetSP();
240   if (loc_sp) {
241     std::lock_guard<std::recursive_mutex> guard(
242         loc_sp->GetTarget().GetAPIMutex());
243     loc_sp->SetThreadName(thread_name);
244   }
245 }
246 
247 const char *SBBreakpointLocation::GetThreadName() const {
248   BreakpointLocationSP loc_sp = GetSP();
249   if (loc_sp) {
250     std::lock_guard<std::recursive_mutex> guard(
251         loc_sp->GetTarget().GetAPIMutex());
252     return loc_sp->GetThreadName();
253   }
254   return NULL;
255 }
256 
257 void SBBreakpointLocation::SetQueueName(const char *queue_name) {
258   BreakpointLocationSP loc_sp = GetSP();
259   if (loc_sp) {
260     std::lock_guard<std::recursive_mutex> guard(
261         loc_sp->GetTarget().GetAPIMutex());
262     loc_sp->SetQueueName(queue_name);
263   }
264 }
265 
266 const char *SBBreakpointLocation::GetQueueName() const {
267   BreakpointLocationSP loc_sp = GetSP();
268   if (loc_sp) {
269     std::lock_guard<std::recursive_mutex> guard(
270         loc_sp->GetTarget().GetAPIMutex());
271     loc_sp->GetQueueName();
272   }
273   return NULL;
274 }
275 
276 bool SBBreakpointLocation::IsResolved() {
277   BreakpointLocationSP loc_sp = GetSP();
278   if (loc_sp) {
279     std::lock_guard<std::recursive_mutex> guard(
280         loc_sp->GetTarget().GetAPIMutex());
281     return loc_sp->IsResolved();
282   }
283   return false;
284 }
285 
286 void SBBreakpointLocation::SetLocation(
287     const lldb::BreakpointLocationSP &break_loc_sp) {
288   // Uninstall the callbacks?
289   m_opaque_wp = break_loc_sp;
290 }
291 
292 bool SBBreakpointLocation::GetDescription(SBStream &description,
293                                           DescriptionLevel level) {
294   Stream &strm = description.ref();
295   BreakpointLocationSP loc_sp = GetSP();
296 
297   if (loc_sp) {
298     std::lock_guard<std::recursive_mutex> guard(
299         loc_sp->GetTarget().GetAPIMutex());
300     loc_sp->GetDescription(&strm, level);
301     strm.EOL();
302   } else
303     strm.PutCString("No value");
304 
305   return true;
306 }
307 
308 break_id_t SBBreakpointLocation::GetID() {
309   BreakpointLocationSP loc_sp = GetSP();
310   if (loc_sp) {
311     std::lock_guard<std::recursive_mutex> guard(
312         loc_sp->GetTarget().GetAPIMutex());
313     return loc_sp->GetID();
314   } else
315     return LLDB_INVALID_BREAK_ID;
316 }
317 
318 SBBreakpoint SBBreakpointLocation::GetBreakpoint() {
319   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
320   BreakpointLocationSP loc_sp = GetSP();
321 
322   SBBreakpoint sb_bp;
323   if (loc_sp) {
324     std::lock_guard<std::recursive_mutex> guard(
325         loc_sp->GetTarget().GetAPIMutex());
326     sb_bp = loc_sp->GetBreakpoint().shared_from_this();
327   }
328 
329   if (log) {
330     SBStream sstr;
331     sb_bp.GetDescription(sstr);
332     LLDB_LOG(log, "location = {0}, breakpoint = {1} ({2})", loc_sp.get(),
333              sb_bp.GetSP().get(), sstr.GetData());
334   }
335   return sb_bp;
336 }
337