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 
66   return bool(m_opaque_wp.lock());
67 }
68 
69 SBError SBWatchpoint::GetError() {
70   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBWatchpoint, GetError);
71 
72   SBError sb_error;
73   lldb::WatchpointSP watchpoint_sp(GetSP());
74   if (watchpoint_sp) {
75     sb_error.SetError(watchpoint_sp->GetError());
76   }
77   return LLDB_RECORD_RESULT(sb_error);
78 }
79 
80 int32_t SBWatchpoint::GetHardwareIndex() {
81   LLDB_RECORD_METHOD_NO_ARGS(int32_t, SBWatchpoint, GetHardwareIndex);
82 
83   int32_t hw_index = -1;
84 
85   lldb::WatchpointSP watchpoint_sp(GetSP());
86   if (watchpoint_sp) {
87     std::lock_guard<std::recursive_mutex> guard(
88         watchpoint_sp->GetTarget().GetAPIMutex());
89     hw_index = watchpoint_sp->GetHardwareIndex();
90   }
91 
92   return hw_index;
93 }
94 
95 addr_t SBWatchpoint::GetWatchAddress() {
96   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBWatchpoint, GetWatchAddress);
97 
98   addr_t ret_addr = LLDB_INVALID_ADDRESS;
99 
100   lldb::WatchpointSP watchpoint_sp(GetSP());
101   if (watchpoint_sp) {
102     std::lock_guard<std::recursive_mutex> guard(
103         watchpoint_sp->GetTarget().GetAPIMutex());
104     ret_addr = watchpoint_sp->GetLoadAddress();
105   }
106 
107   return ret_addr;
108 }
109 
110 size_t SBWatchpoint::GetWatchSize() {
111   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBWatchpoint, GetWatchSize);
112 
113   size_t watch_size = 0;
114 
115   lldb::WatchpointSP watchpoint_sp(GetSP());
116   if (watchpoint_sp) {
117     std::lock_guard<std::recursive_mutex> guard(
118         watchpoint_sp->GetTarget().GetAPIMutex());
119     watch_size = watchpoint_sp->GetByteSize();
120   }
121 
122   return watch_size;
123 }
124 
125 void SBWatchpoint::SetEnabled(bool enabled) {
126   LLDB_RECORD_METHOD(void, SBWatchpoint, SetEnabled, (bool), enabled);
127 
128   lldb::WatchpointSP watchpoint_sp(GetSP());
129   if (watchpoint_sp) {
130     Target &target = watchpoint_sp->GetTarget();
131     std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
132     ProcessSP process_sp = target.GetProcessSP();
133     const bool notify = true;
134     if (process_sp) {
135       if (enabled)
136         process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
137       else
138         process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
139     } else {
140       watchpoint_sp->SetEnabled(enabled, notify);
141     }
142   }
143 }
144 
145 bool SBWatchpoint::IsEnabled() {
146   LLDB_RECORD_METHOD_NO_ARGS(bool, SBWatchpoint, IsEnabled);
147 
148   lldb::WatchpointSP watchpoint_sp(GetSP());
149   if (watchpoint_sp) {
150     std::lock_guard<std::recursive_mutex> guard(
151         watchpoint_sp->GetTarget().GetAPIMutex());
152     return watchpoint_sp->IsEnabled();
153   } else
154     return false;
155 }
156 
157 uint32_t SBWatchpoint::GetHitCount() {
158   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBWatchpoint, GetHitCount);
159 
160   uint32_t count = 0;
161   lldb::WatchpointSP watchpoint_sp(GetSP());
162   if (watchpoint_sp) {
163     std::lock_guard<std::recursive_mutex> guard(
164         watchpoint_sp->GetTarget().GetAPIMutex());
165     count = watchpoint_sp->GetHitCount();
166   }
167 
168   return count;
169 }
170 
171 uint32_t SBWatchpoint::GetIgnoreCount() {
172   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBWatchpoint, GetIgnoreCount);
173 
174   lldb::WatchpointSP watchpoint_sp(GetSP());
175   if (watchpoint_sp) {
176     std::lock_guard<std::recursive_mutex> guard(
177         watchpoint_sp->GetTarget().GetAPIMutex());
178     return watchpoint_sp->GetIgnoreCount();
179   } else
180     return 0;
181 }
182 
183 void SBWatchpoint::SetIgnoreCount(uint32_t n) {
184   LLDB_RECORD_METHOD(void, SBWatchpoint, SetIgnoreCount, (uint32_t), n);
185 
186   lldb::WatchpointSP watchpoint_sp(GetSP());
187   if (watchpoint_sp) {
188     std::lock_guard<std::recursive_mutex> guard(
189         watchpoint_sp->GetTarget().GetAPIMutex());
190     watchpoint_sp->SetIgnoreCount(n);
191   }
192 }
193 
194 const char *SBWatchpoint::GetCondition() {
195   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBWatchpoint, GetCondition);
196 
197   lldb::WatchpointSP watchpoint_sp(GetSP());
198   if (watchpoint_sp) {
199     std::lock_guard<std::recursive_mutex> guard(
200         watchpoint_sp->GetTarget().GetAPIMutex());
201     return watchpoint_sp->GetConditionText();
202   }
203   return NULL;
204 }
205 
206 void SBWatchpoint::SetCondition(const char *condition) {
207   LLDB_RECORD_METHOD(void, SBWatchpoint, SetCondition, (const char *),
208                      condition);
209 
210   lldb::WatchpointSP watchpoint_sp(GetSP());
211   if (watchpoint_sp) {
212     std::lock_guard<std::recursive_mutex> guard(
213         watchpoint_sp->GetTarget().GetAPIMutex());
214     watchpoint_sp->SetCondition(condition);
215   }
216 }
217 
218 bool SBWatchpoint::GetDescription(SBStream &description,
219                                   DescriptionLevel level) {
220   LLDB_RECORD_METHOD(bool, SBWatchpoint, GetDescription,
221                      (lldb::SBStream &, lldb::DescriptionLevel), description,
222                      level);
223 
224   Stream &strm = description.ref();
225 
226   lldb::WatchpointSP watchpoint_sp(GetSP());
227   if (watchpoint_sp) {
228     std::lock_guard<std::recursive_mutex> guard(
229         watchpoint_sp->GetTarget().GetAPIMutex());
230     watchpoint_sp->GetDescription(&strm, level);
231     strm.EOL();
232   } else
233     strm.PutCString("No value");
234 
235   return true;
236 }
237 
238 void SBWatchpoint::Clear() {
239   LLDB_RECORD_METHOD_NO_ARGS(void, SBWatchpoint, Clear);
240 
241   m_opaque_wp.reset();
242 }
243 
244 lldb::WatchpointSP SBWatchpoint::GetSP() const {
245   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::WatchpointSP, SBWatchpoint, GetSP);
246 
247   return LLDB_RECORD_RESULT(m_opaque_wp.lock());
248 }
249 
250 void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) {
251   LLDB_RECORD_METHOD(void, SBWatchpoint, SetSP, (const lldb::WatchpointSP &),
252                      sp);
253 
254   m_opaque_wp = sp;
255 }
256 
257 bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) {
258   LLDB_RECORD_STATIC_METHOD(bool, SBWatchpoint, EventIsWatchpointEvent,
259                             (const lldb::SBEvent &), event);
260 
261   return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) !=
262          NULL;
263 }
264 
265 WatchpointEventType
266 SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) {
267   LLDB_RECORD_STATIC_METHOD(lldb::WatchpointEventType, SBWatchpoint,
268                             GetWatchpointEventTypeFromEvent,
269                             (const lldb::SBEvent &), event);
270 
271   if (event.IsValid())
272     return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent(
273         event.GetSP());
274   return eWatchpointEventTypeInvalidType;
275 }
276 
277 SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) {
278   LLDB_RECORD_STATIC_METHOD(lldb::SBWatchpoint, SBWatchpoint,
279                             GetWatchpointFromEvent, (const lldb::SBEvent &),
280                             event);
281 
282   SBWatchpoint sb_watchpoint;
283   if (event.IsValid())
284     sb_watchpoint =
285         Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP());
286   return LLDB_RECORD_RESULT(sb_watchpoint);
287 }
288