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