1 //===-- SBWatchpoint.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/SBWatchpoint.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/SBEvent.h"
15 #include "lldb/API/SBStream.h"
16 
17 #include "lldb/Breakpoint/Watchpoint.h"
18 #include "lldb/Breakpoint/WatchpointList.h"
19 #include "lldb/Core/StreamFile.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/Stream.h"
23 #include "lldb/lldb-defines.h"
24 #include "lldb/lldb-types.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 SBWatchpoint::SBWatchpoint() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBWatchpoint); }
30 
31 SBWatchpoint::SBWatchpoint(const lldb::WatchpointSP &wp_sp)
32     : m_opaque_wp(wp_sp) {
33   LLDB_RECORD_CONSTRUCTOR(SBWatchpoint, (const lldb::WatchpointSP &), wp_sp);
34 }
35 
36 SBWatchpoint::SBWatchpoint(const SBWatchpoint &rhs)
37     : m_opaque_wp(rhs.m_opaque_wp) {
38   LLDB_RECORD_CONSTRUCTOR(SBWatchpoint, (const lldb::SBWatchpoint &), rhs);
39 }
40 
41 const SBWatchpoint &SBWatchpoint::operator=(const SBWatchpoint &rhs) {
42   LLDB_RECORD_METHOD(const lldb::SBWatchpoint &,
43                      SBWatchpoint, operator=,(const lldb::SBWatchpoint &), rhs);
44 
45   m_opaque_wp = rhs.m_opaque_wp;
46   return *this;
47 }
48 
49 SBWatchpoint::~SBWatchpoint() {}
50 
51 watch_id_t SBWatchpoint::GetID() {
52   LLDB_RECORD_METHOD_NO_ARGS(lldb::watch_id_t, SBWatchpoint, GetID);
53 
54 
55   watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
56   lldb::WatchpointSP watchpoint_sp(GetSP());
57   if (watchpoint_sp)
58     watch_id = watchpoint_sp->GetID();
59 
60   return watch_id;
61 }
62 
63 bool SBWatchpoint::IsValid() const {
64   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBWatchpoint, IsValid);
65   return this->operator bool();
66 }
67 SBWatchpoint::operator bool() const {
68   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBWatchpoint, operator bool);
69 
70   return bool(m_opaque_wp.lock());
71 }
72 
73 SBError SBWatchpoint::GetError() {
74   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBWatchpoint, GetError);
75 
76   SBError sb_error;
77   lldb::WatchpointSP watchpoint_sp(GetSP());
78   if (watchpoint_sp) {
79     sb_error.SetError(watchpoint_sp->GetError());
80   }
81   return LLDB_RECORD_RESULT(sb_error);
82 }
83 
84 int32_t SBWatchpoint::GetHardwareIndex() {
85   LLDB_RECORD_METHOD_NO_ARGS(int32_t, SBWatchpoint, GetHardwareIndex);
86 
87   int32_t hw_index = -1;
88 
89   lldb::WatchpointSP watchpoint_sp(GetSP());
90   if (watchpoint_sp) {
91     std::lock_guard<std::recursive_mutex> guard(
92         watchpoint_sp->GetTarget().GetAPIMutex());
93     hw_index = watchpoint_sp->GetHardwareIndex();
94   }
95 
96   return hw_index;
97 }
98 
99 addr_t SBWatchpoint::GetWatchAddress() {
100   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBWatchpoint, GetWatchAddress);
101 
102   addr_t ret_addr = LLDB_INVALID_ADDRESS;
103 
104   lldb::WatchpointSP watchpoint_sp(GetSP());
105   if (watchpoint_sp) {
106     std::lock_guard<std::recursive_mutex> guard(
107         watchpoint_sp->GetTarget().GetAPIMutex());
108     ret_addr = watchpoint_sp->GetLoadAddress();
109   }
110 
111   return ret_addr;
112 }
113 
114 size_t SBWatchpoint::GetWatchSize() {
115   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBWatchpoint, GetWatchSize);
116 
117   size_t watch_size = 0;
118 
119   lldb::WatchpointSP watchpoint_sp(GetSP());
120   if (watchpoint_sp) {
121     std::lock_guard<std::recursive_mutex> guard(
122         watchpoint_sp->GetTarget().GetAPIMutex());
123     watch_size = watchpoint_sp->GetByteSize();
124   }
125 
126   return watch_size;
127 }
128 
129 void SBWatchpoint::SetEnabled(bool enabled) {
130   LLDB_RECORD_METHOD(void, SBWatchpoint, SetEnabled, (bool), enabled);
131 
132   lldb::WatchpointSP watchpoint_sp(GetSP());
133   if (watchpoint_sp) {
134     Target &target = watchpoint_sp->GetTarget();
135     std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
136     ProcessSP process_sp = target.GetProcessSP();
137     const bool notify = true;
138     if (process_sp) {
139       if (enabled)
140         process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
141       else
142         process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
143     } else {
144       watchpoint_sp->SetEnabled(enabled, notify);
145     }
146   }
147 }
148 
149 bool SBWatchpoint::IsEnabled() {
150   LLDB_RECORD_METHOD_NO_ARGS(bool, SBWatchpoint, IsEnabled);
151 
152   lldb::WatchpointSP watchpoint_sp(GetSP());
153   if (watchpoint_sp) {
154     std::lock_guard<std::recursive_mutex> guard(
155         watchpoint_sp->GetTarget().GetAPIMutex());
156     return watchpoint_sp->IsEnabled();
157   } else
158     return false;
159 }
160 
161 uint32_t SBWatchpoint::GetHitCount() {
162   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBWatchpoint, GetHitCount);
163 
164   uint32_t count = 0;
165   lldb::WatchpointSP watchpoint_sp(GetSP());
166   if (watchpoint_sp) {
167     std::lock_guard<std::recursive_mutex> guard(
168         watchpoint_sp->GetTarget().GetAPIMutex());
169     count = watchpoint_sp->GetHitCount();
170   }
171 
172   return count;
173 }
174 
175 uint32_t SBWatchpoint::GetIgnoreCount() {
176   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBWatchpoint, GetIgnoreCount);
177 
178   lldb::WatchpointSP watchpoint_sp(GetSP());
179   if (watchpoint_sp) {
180     std::lock_guard<std::recursive_mutex> guard(
181         watchpoint_sp->GetTarget().GetAPIMutex());
182     return watchpoint_sp->GetIgnoreCount();
183   } else
184     return 0;
185 }
186 
187 void SBWatchpoint::SetIgnoreCount(uint32_t n) {
188   LLDB_RECORD_METHOD(void, SBWatchpoint, SetIgnoreCount, (uint32_t), n);
189 
190   lldb::WatchpointSP watchpoint_sp(GetSP());
191   if (watchpoint_sp) {
192     std::lock_guard<std::recursive_mutex> guard(
193         watchpoint_sp->GetTarget().GetAPIMutex());
194     watchpoint_sp->SetIgnoreCount(n);
195   }
196 }
197 
198 const char *SBWatchpoint::GetCondition() {
199   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBWatchpoint, GetCondition);
200 
201   lldb::WatchpointSP watchpoint_sp(GetSP());
202   if (watchpoint_sp) {
203     std::lock_guard<std::recursive_mutex> guard(
204         watchpoint_sp->GetTarget().GetAPIMutex());
205     return watchpoint_sp->GetConditionText();
206   }
207   return NULL;
208 }
209 
210 void SBWatchpoint::SetCondition(const char *condition) {
211   LLDB_RECORD_METHOD(void, SBWatchpoint, SetCondition, (const char *),
212                      condition);
213 
214   lldb::WatchpointSP watchpoint_sp(GetSP());
215   if (watchpoint_sp) {
216     std::lock_guard<std::recursive_mutex> guard(
217         watchpoint_sp->GetTarget().GetAPIMutex());
218     watchpoint_sp->SetCondition(condition);
219   }
220 }
221 
222 bool SBWatchpoint::GetDescription(SBStream &description,
223                                   DescriptionLevel level) {
224   LLDB_RECORD_METHOD(bool, SBWatchpoint, GetDescription,
225                      (lldb::SBStream &, lldb::DescriptionLevel), description,
226                      level);
227 
228   Stream &strm = description.ref();
229 
230   lldb::WatchpointSP watchpoint_sp(GetSP());
231   if (watchpoint_sp) {
232     std::lock_guard<std::recursive_mutex> guard(
233         watchpoint_sp->GetTarget().GetAPIMutex());
234     watchpoint_sp->GetDescription(&strm, level);
235     strm.EOL();
236   } else
237     strm.PutCString("No value");
238 
239   return true;
240 }
241 
242 void SBWatchpoint::Clear() {
243   LLDB_RECORD_METHOD_NO_ARGS(void, SBWatchpoint, Clear);
244 
245   m_opaque_wp.reset();
246 }
247 
248 lldb::WatchpointSP SBWatchpoint::GetSP() const {
249   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::WatchpointSP, SBWatchpoint, GetSP);
250 
251   return LLDB_RECORD_RESULT(m_opaque_wp.lock());
252 }
253 
254 void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) {
255   LLDB_RECORD_METHOD(void, SBWatchpoint, SetSP, (const lldb::WatchpointSP &),
256                      sp);
257 
258   m_opaque_wp = sp;
259 }
260 
261 bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) {
262   LLDB_RECORD_STATIC_METHOD(bool, SBWatchpoint, EventIsWatchpointEvent,
263                             (const lldb::SBEvent &), event);
264 
265   return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) !=
266          NULL;
267 }
268 
269 WatchpointEventType
270 SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) {
271   LLDB_RECORD_STATIC_METHOD(lldb::WatchpointEventType, SBWatchpoint,
272                             GetWatchpointEventTypeFromEvent,
273                             (const lldb::SBEvent &), event);
274 
275   if (event.IsValid())
276     return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent(
277         event.GetSP());
278   return eWatchpointEventTypeInvalidType;
279 }
280 
281 SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) {
282   LLDB_RECORD_STATIC_METHOD(lldb::SBWatchpoint, SBWatchpoint,
283                             GetWatchpointFromEvent, (const lldb::SBEvent &),
284                             event);
285 
286   SBWatchpoint sb_watchpoint;
287   if (event.IsValid())
288     sb_watchpoint =
289         Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP());
290   return LLDB_RECORD_RESULT(sb_watchpoint);
291 }
292 
293 namespace lldb_private {
294 namespace repro {
295 
296 template <>
297 void RegisterMethods<SBWatchpoint>(Registry &R) {
298   LLDB_REGISTER_CONSTRUCTOR(SBWatchpoint, ());
299   LLDB_REGISTER_CONSTRUCTOR(SBWatchpoint, (const lldb::WatchpointSP &));
300   LLDB_REGISTER_CONSTRUCTOR(SBWatchpoint, (const lldb::SBWatchpoint &));
301   LLDB_REGISTER_METHOD(const lldb::SBWatchpoint &,
302                        SBWatchpoint, operator=,(const lldb::SBWatchpoint &));
303   LLDB_REGISTER_METHOD(lldb::watch_id_t, SBWatchpoint, GetID, ());
304   LLDB_REGISTER_METHOD_CONST(bool, SBWatchpoint, IsValid, ());
305   LLDB_REGISTER_METHOD_CONST(bool, SBWatchpoint, operator bool, ());
306   LLDB_REGISTER_METHOD(lldb::SBError, SBWatchpoint, GetError, ());
307   LLDB_REGISTER_METHOD(int32_t, SBWatchpoint, GetHardwareIndex, ());
308   LLDB_REGISTER_METHOD(lldb::addr_t, SBWatchpoint, GetWatchAddress, ());
309   LLDB_REGISTER_METHOD(size_t, SBWatchpoint, GetWatchSize, ());
310   LLDB_REGISTER_METHOD(void, SBWatchpoint, SetEnabled, (bool));
311   LLDB_REGISTER_METHOD(bool, SBWatchpoint, IsEnabled, ());
312   LLDB_REGISTER_METHOD(uint32_t, SBWatchpoint, GetHitCount, ());
313   LLDB_REGISTER_METHOD(uint32_t, SBWatchpoint, GetIgnoreCount, ());
314   LLDB_REGISTER_METHOD(void, SBWatchpoint, SetIgnoreCount, (uint32_t));
315   LLDB_REGISTER_METHOD(const char *, SBWatchpoint, GetCondition, ());
316   LLDB_REGISTER_METHOD(void, SBWatchpoint, SetCondition, (const char *));
317   LLDB_REGISTER_METHOD(bool, SBWatchpoint, GetDescription,
318                        (lldb::SBStream &, lldb::DescriptionLevel));
319   LLDB_REGISTER_METHOD(void, SBWatchpoint, Clear, ());
320   LLDB_REGISTER_METHOD_CONST(lldb::WatchpointSP, SBWatchpoint, GetSP, ());
321   LLDB_REGISTER_METHOD(void, SBWatchpoint, SetSP,
322                        (const lldb::WatchpointSP &));
323   LLDB_REGISTER_STATIC_METHOD(bool, SBWatchpoint, EventIsWatchpointEvent,
324                               (const lldb::SBEvent &));
325   LLDB_REGISTER_STATIC_METHOD(lldb::WatchpointEventType, SBWatchpoint,
326                               GetWatchpointEventTypeFromEvent,
327                               (const lldb::SBEvent &));
328   LLDB_REGISTER_STATIC_METHOD(lldb::SBWatchpoint, SBWatchpoint,
329                               GetWatchpointFromEvent,
330                               (const lldb::SBEvent &));
331 }
332 
333 }
334 }
335