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 "lldb/API/SBAddress.h"
11 #include "lldb/API/SBDebugger.h"
12 #include "lldb/API/SBDefines.h"
13 #include "lldb/API/SBEvent.h"
14 #include "lldb/API/SBStream.h"
15 
16 #include "lldb/Breakpoint/Watchpoint.h"
17 #include "lldb/Breakpoint/WatchpointList.h"
18 #include "lldb/Core/StreamFile.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Utility/Log.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() {}
30 
31 SBWatchpoint::SBWatchpoint(const lldb::WatchpointSP &wp_sp)
32     : m_opaque_wp(wp_sp) {
33   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
34 
35   if (log) {
36     SBStream sstr;
37     GetDescription(sstr, lldb::eDescriptionLevelBrief);
38     LLDB_LOG(log, "watchpoint = {0} ({1})", wp_sp.get(), sstr.GetData());
39   }
40 }
41 
42 SBWatchpoint::SBWatchpoint(const SBWatchpoint &rhs)
43     : m_opaque_wp(rhs.m_opaque_wp) {}
44 
45 const SBWatchpoint &SBWatchpoint::operator=(const SBWatchpoint &rhs) {
46   m_opaque_wp = rhs.m_opaque_wp;
47   return *this;
48 }
49 
50 SBWatchpoint::~SBWatchpoint() {}
51 
52 watch_id_t SBWatchpoint::GetID() {
53   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
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   if (log) {
61     if (watch_id == LLDB_INVALID_WATCH_ID)
62       log->Printf("SBWatchpoint(%p)::GetID () => LLDB_INVALID_WATCH_ID",
63                   static_cast<void *>(watchpoint_sp.get()));
64     else
65       log->Printf("SBWatchpoint(%p)::GetID () => %u",
66                   static_cast<void *>(watchpoint_sp.get()), watch_id);
67   }
68 
69   return watch_id;
70 }
71 
72 bool SBWatchpoint::IsValid() const { return bool(m_opaque_wp.lock()); }
73 
74 SBError SBWatchpoint::GetError() {
75   SBError sb_error;
76   lldb::WatchpointSP watchpoint_sp(GetSP());
77   if (watchpoint_sp) {
78     sb_error.SetError(watchpoint_sp->GetError());
79   }
80   return sb_error;
81 }
82 
83 int32_t SBWatchpoint::GetHardwareIndex() {
84   int32_t hw_index = -1;
85 
86   lldb::WatchpointSP watchpoint_sp(GetSP());
87   if (watchpoint_sp) {
88     std::lock_guard<std::recursive_mutex> guard(
89         watchpoint_sp->GetTarget().GetAPIMutex());
90     hw_index = watchpoint_sp->GetHardwareIndex();
91   }
92 
93   return hw_index;
94 }
95 
96 addr_t SBWatchpoint::GetWatchAddress() {
97   addr_t ret_addr = LLDB_INVALID_ADDRESS;
98 
99   lldb::WatchpointSP watchpoint_sp(GetSP());
100   if (watchpoint_sp) {
101     std::lock_guard<std::recursive_mutex> guard(
102         watchpoint_sp->GetTarget().GetAPIMutex());
103     ret_addr = watchpoint_sp->GetLoadAddress();
104   }
105 
106   return ret_addr;
107 }
108 
109 size_t SBWatchpoint::GetWatchSize() {
110   size_t watch_size = 0;
111 
112   lldb::WatchpointSP watchpoint_sp(GetSP());
113   if (watchpoint_sp) {
114     std::lock_guard<std::recursive_mutex> guard(
115         watchpoint_sp->GetTarget().GetAPIMutex());
116     watch_size = watchpoint_sp->GetByteSize();
117   }
118 
119   return watch_size;
120 }
121 
122 void SBWatchpoint::SetEnabled(bool enabled) {
123   lldb::WatchpointSP watchpoint_sp(GetSP());
124   if (watchpoint_sp) {
125     Target &target = watchpoint_sp->GetTarget();
126     std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
127     ProcessSP process_sp = target.GetProcessSP();
128     const bool notify = true;
129     if (process_sp) {
130       if (enabled)
131         process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
132       else
133         process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
134     } else {
135       watchpoint_sp->SetEnabled(enabled, notify);
136     }
137   }
138 }
139 
140 bool SBWatchpoint::IsEnabled() {
141   lldb::WatchpointSP watchpoint_sp(GetSP());
142   if (watchpoint_sp) {
143     std::lock_guard<std::recursive_mutex> guard(
144         watchpoint_sp->GetTarget().GetAPIMutex());
145     return watchpoint_sp->IsEnabled();
146   } else
147     return false;
148 }
149 
150 uint32_t SBWatchpoint::GetHitCount() {
151   uint32_t count = 0;
152   lldb::WatchpointSP watchpoint_sp(GetSP());
153   if (watchpoint_sp) {
154     std::lock_guard<std::recursive_mutex> guard(
155         watchpoint_sp->GetTarget().GetAPIMutex());
156     count = watchpoint_sp->GetHitCount();
157   }
158 
159   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
160   if (log)
161     log->Printf("SBWatchpoint(%p)::GetHitCount () => %u",
162                 static_cast<void *>(watchpoint_sp.get()), count);
163 
164   return count;
165 }
166 
167 uint32_t SBWatchpoint::GetIgnoreCount() {
168   lldb::WatchpointSP watchpoint_sp(GetSP());
169   if (watchpoint_sp) {
170     std::lock_guard<std::recursive_mutex> guard(
171         watchpoint_sp->GetTarget().GetAPIMutex());
172     return watchpoint_sp->GetIgnoreCount();
173   } else
174     return 0;
175 }
176 
177 void SBWatchpoint::SetIgnoreCount(uint32_t n) {
178   lldb::WatchpointSP watchpoint_sp(GetSP());
179   if (watchpoint_sp) {
180     std::lock_guard<std::recursive_mutex> guard(
181         watchpoint_sp->GetTarget().GetAPIMutex());
182     watchpoint_sp->SetIgnoreCount(n);
183   }
184 }
185 
186 const char *SBWatchpoint::GetCondition() {
187   lldb::WatchpointSP watchpoint_sp(GetSP());
188   if (watchpoint_sp) {
189     std::lock_guard<std::recursive_mutex> guard(
190         watchpoint_sp->GetTarget().GetAPIMutex());
191     return watchpoint_sp->GetConditionText();
192   }
193   return NULL;
194 }
195 
196 void SBWatchpoint::SetCondition(const char *condition) {
197   lldb::WatchpointSP watchpoint_sp(GetSP());
198   if (watchpoint_sp) {
199     std::lock_guard<std::recursive_mutex> guard(
200         watchpoint_sp->GetTarget().GetAPIMutex());
201     watchpoint_sp->SetCondition(condition);
202   }
203 }
204 
205 bool SBWatchpoint::GetDescription(SBStream &description,
206                                   DescriptionLevel level) {
207   Stream &strm = description.ref();
208 
209   lldb::WatchpointSP watchpoint_sp(GetSP());
210   if (watchpoint_sp) {
211     std::lock_guard<std::recursive_mutex> guard(
212         watchpoint_sp->GetTarget().GetAPIMutex());
213     watchpoint_sp->GetDescription(&strm, level);
214     strm.EOL();
215   } else
216     strm.PutCString("No value");
217 
218   return true;
219 }
220 
221 void SBWatchpoint::Clear() { m_opaque_wp.reset(); }
222 
223 lldb::WatchpointSP SBWatchpoint::GetSP() const { return m_opaque_wp.lock(); }
224 
225 void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) { m_opaque_wp = sp; }
226 
227 bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) {
228   return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) !=
229          NULL;
230 }
231 
232 WatchpointEventType
233 SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) {
234   if (event.IsValid())
235     return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent(
236         event.GetSP());
237   return eWatchpointEventTypeInvalidType;
238 }
239 
240 SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) {
241   SBWatchpoint sb_watchpoint;
242   if (event.IsValid())
243     sb_watchpoint =
244         Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP());
245   return sb_watchpoint;
246 }
247