/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/API/SBWatchpoint.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- SBWatchpoint.cpp --------------------------------------------------===// |
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 | | #include "lldb/Utility/Instrumentation.h" |
16 | | |
17 | | #include "lldb/Breakpoint/Watchpoint.h" |
18 | | #include "lldb/Breakpoint/WatchpointList.h" |
19 | | #include "lldb/Symbol/CompilerType.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 | 158 | SBWatchpoint::SBWatchpoint() { LLDB_INSTRUMENT_VA(this); } |
30 | | |
31 | | SBWatchpoint::SBWatchpoint(const lldb::WatchpointSP &wp_sp) |
32 | 11 | : m_opaque_wp(wp_sp) { |
33 | 11 | LLDB_INSTRUMENT_VA(this, wp_sp); |
34 | 11 | } |
35 | | |
36 | | SBWatchpoint::SBWatchpoint(const SBWatchpoint &rhs) |
37 | 78 | : m_opaque_wp(rhs.m_opaque_wp) { |
38 | 78 | LLDB_INSTRUMENT_VA(this, rhs); |
39 | 78 | } |
40 | | |
41 | 79 | const SBWatchpoint &SBWatchpoint::operator=(const SBWatchpoint &rhs) { |
42 | 79 | LLDB_INSTRUMENT_VA(this, rhs); |
43 | | |
44 | 79 | m_opaque_wp = rhs.m_opaque_wp; |
45 | 79 | return *this; |
46 | 79 | } |
47 | | |
48 | 247 | SBWatchpoint::~SBWatchpoint() = default; |
49 | | |
50 | 3 | watch_id_t SBWatchpoint::GetID() { |
51 | 3 | LLDB_INSTRUMENT_VA(this); |
52 | | |
53 | 3 | watch_id_t watch_id = LLDB_INVALID_WATCH_ID; |
54 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
55 | 3 | if (watchpoint_sp) |
56 | 2 | watch_id = watchpoint_sp->GetID(); |
57 | | |
58 | 3 | return watch_id; |
59 | 3 | } |
60 | | |
61 | 6 | bool SBWatchpoint::IsValid() const { |
62 | 6 | LLDB_INSTRUMENT_VA(this); |
63 | 6 | return this->operator bool(); |
64 | 6 | } |
65 | 18 | SBWatchpoint::operator bool() const { |
66 | 18 | LLDB_INSTRUMENT_VA(this); |
67 | | |
68 | 18 | return bool(m_opaque_wp.lock()); |
69 | 18 | } |
70 | | |
71 | 0 | bool SBWatchpoint::operator==(const SBWatchpoint &rhs) const { |
72 | 0 | LLDB_INSTRUMENT_VA(this, rhs); |
73 | |
|
74 | 0 | return GetSP() == rhs.GetSP(); |
75 | 0 | } |
76 | | |
77 | 0 | bool SBWatchpoint::operator!=(const SBWatchpoint &rhs) const { |
78 | 0 | LLDB_INSTRUMENT_VA(this, rhs); |
79 | |
|
80 | 0 | return !(*this == rhs); |
81 | 0 | } |
82 | | |
83 | 0 | SBError SBWatchpoint::GetError() { |
84 | 0 | LLDB_INSTRUMENT_VA(this); |
85 | |
|
86 | 0 | SBError sb_error; |
87 | 0 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
88 | 0 | if (watchpoint_sp) { |
89 | 0 | sb_error.SetError(watchpoint_sp->GetError()); |
90 | 0 | } |
91 | 0 | return sb_error; |
92 | 0 | } |
93 | | |
94 | 3 | int32_t SBWatchpoint::GetHardwareIndex() { |
95 | 3 | LLDB_INSTRUMENT_VA(this); |
96 | | |
97 | 3 | int32_t hw_index = -1; |
98 | | |
99 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
100 | 3 | if (watchpoint_sp) { |
101 | 2 | std::lock_guard<std::recursive_mutex> guard( |
102 | 2 | watchpoint_sp->GetTarget().GetAPIMutex()); |
103 | 2 | hw_index = watchpoint_sp->GetHardwareIndex(); |
104 | 2 | } |
105 | | |
106 | 3 | return hw_index; |
107 | 3 | } |
108 | | |
109 | 4 | addr_t SBWatchpoint::GetWatchAddress() { |
110 | 4 | LLDB_INSTRUMENT_VA(this); |
111 | | |
112 | 4 | addr_t ret_addr = LLDB_INVALID_ADDRESS; |
113 | | |
114 | 4 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
115 | 4 | if (watchpoint_sp) { |
116 | 3 | std::lock_guard<std::recursive_mutex> guard( |
117 | 3 | watchpoint_sp->GetTarget().GetAPIMutex()); |
118 | 3 | ret_addr = watchpoint_sp->GetLoadAddress(); |
119 | 3 | } |
120 | | |
121 | 4 | return ret_addr; |
122 | 4 | } |
123 | | |
124 | 4 | size_t SBWatchpoint::GetWatchSize() { |
125 | 4 | LLDB_INSTRUMENT_VA(this); |
126 | | |
127 | 4 | size_t watch_size = 0; |
128 | | |
129 | 4 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
130 | 4 | if (watchpoint_sp) { |
131 | 3 | std::lock_guard<std::recursive_mutex> guard( |
132 | 3 | watchpoint_sp->GetTarget().GetAPIMutex()); |
133 | 3 | watch_size = watchpoint_sp->GetByteSize(); |
134 | 3 | } |
135 | | |
136 | 4 | return watch_size; |
137 | 4 | } |
138 | | |
139 | 7 | void SBWatchpoint::SetEnabled(bool enabled) { |
140 | 7 | LLDB_INSTRUMENT_VA(this, enabled); |
141 | | |
142 | 7 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
143 | 7 | if (watchpoint_sp) { |
144 | 6 | Target &target = watchpoint_sp->GetTarget(); |
145 | 6 | std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex()); |
146 | 6 | ProcessSP process_sp = target.GetProcessSP(); |
147 | 6 | const bool notify = true; |
148 | 6 | if (process_sp) { |
149 | 6 | if (enabled) |
150 | 2 | process_sp->EnableWatchpoint(watchpoint_sp.get(), notify); |
151 | 4 | else |
152 | 4 | process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); |
153 | 6 | } else { |
154 | 0 | watchpoint_sp->SetEnabled(enabled, notify); |
155 | 0 | } |
156 | 6 | } |
157 | 7 | } |
158 | | |
159 | 7 | bool SBWatchpoint::IsEnabled() { |
160 | 7 | LLDB_INSTRUMENT_VA(this); |
161 | | |
162 | 7 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
163 | 7 | if (watchpoint_sp) { |
164 | 6 | std::lock_guard<std::recursive_mutex> guard( |
165 | 6 | watchpoint_sp->GetTarget().GetAPIMutex()); |
166 | 6 | return watchpoint_sp->IsEnabled(); |
167 | 6 | } else |
168 | 1 | return false; |
169 | 7 | } |
170 | | |
171 | 53 | uint32_t SBWatchpoint::GetHitCount() { |
172 | 53 | LLDB_INSTRUMENT_VA(this); |
173 | | |
174 | 53 | uint32_t count = 0; |
175 | 53 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
176 | 53 | if (watchpoint_sp) { |
177 | 52 | std::lock_guard<std::recursive_mutex> guard( |
178 | 52 | watchpoint_sp->GetTarget().GetAPIMutex()); |
179 | 52 | count = watchpoint_sp->GetHitCount(); |
180 | 52 | } |
181 | | |
182 | 53 | return count; |
183 | 53 | } |
184 | | |
185 | 2 | uint32_t SBWatchpoint::GetIgnoreCount() { |
186 | 2 | LLDB_INSTRUMENT_VA(this); |
187 | | |
188 | 2 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
189 | 2 | if (watchpoint_sp) { |
190 | 1 | std::lock_guard<std::recursive_mutex> guard( |
191 | 1 | watchpoint_sp->GetTarget().GetAPIMutex()); |
192 | 1 | return watchpoint_sp->GetIgnoreCount(); |
193 | 1 | } else |
194 | 1 | return 0; |
195 | 2 | } |
196 | | |
197 | 3 | void SBWatchpoint::SetIgnoreCount(uint32_t n) { |
198 | 3 | LLDB_INSTRUMENT_VA(this, n); |
199 | | |
200 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
201 | 3 | if (watchpoint_sp) { |
202 | 2 | std::lock_guard<std::recursive_mutex> guard( |
203 | 2 | watchpoint_sp->GetTarget().GetAPIMutex()); |
204 | 2 | watchpoint_sp->SetIgnoreCount(n); |
205 | 2 | } |
206 | 3 | } |
207 | | |
208 | 3 | const char *SBWatchpoint::GetCondition() { |
209 | 3 | LLDB_INSTRUMENT_VA(this); |
210 | | |
211 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
212 | 3 | if (!watchpoint_sp) |
213 | 1 | return nullptr; |
214 | | |
215 | 2 | std::lock_guard<std::recursive_mutex> guard( |
216 | 2 | watchpoint_sp->GetTarget().GetAPIMutex()); |
217 | 2 | return ConstString(watchpoint_sp->GetConditionText()).GetCString(); |
218 | 3 | } |
219 | | |
220 | 3 | void SBWatchpoint::SetCondition(const char *condition) { |
221 | 3 | LLDB_INSTRUMENT_VA(this, condition); |
222 | | |
223 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
224 | 3 | if (watchpoint_sp) { |
225 | 2 | std::lock_guard<std::recursive_mutex> guard( |
226 | 2 | watchpoint_sp->GetTarget().GetAPIMutex()); |
227 | 2 | watchpoint_sp->SetCondition(condition); |
228 | 2 | } |
229 | 3 | } |
230 | | |
231 | | bool SBWatchpoint::GetDescription(SBStream &description, |
232 | 65 | DescriptionLevel level) { |
233 | 65 | LLDB_INSTRUMENT_VA(this, description, level); |
234 | | |
235 | 65 | Stream &strm = description.ref(); |
236 | | |
237 | 65 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
238 | 65 | if (watchpoint_sp) { |
239 | 63 | std::lock_guard<std::recursive_mutex> guard( |
240 | 63 | watchpoint_sp->GetTarget().GetAPIMutex()); |
241 | 63 | watchpoint_sp->GetDescription(&strm, level); |
242 | 63 | strm.EOL(); |
243 | 63 | } else |
244 | 2 | strm.PutCString("No value"); |
245 | | |
246 | 65 | return true; |
247 | 65 | } |
248 | | |
249 | 0 | void SBWatchpoint::Clear() { |
250 | 0 | LLDB_INSTRUMENT_VA(this); |
251 | |
|
252 | 0 | m_opaque_wp.reset(); |
253 | 0 | } |
254 | | |
255 | 177 | lldb::WatchpointSP SBWatchpoint::GetSP() const { |
256 | 177 | LLDB_INSTRUMENT_VA(this); |
257 | | |
258 | 177 | return m_opaque_wp.lock(); |
259 | 177 | } |
260 | | |
261 | 73 | void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) { |
262 | 73 | LLDB_INSTRUMENT_VA(this, sp); |
263 | | |
264 | 73 | m_opaque_wp = sp; |
265 | 73 | } |
266 | | |
267 | 5 | bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) { |
268 | 5 | LLDB_INSTRUMENT_VA(event); |
269 | | |
270 | 5 | return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) != |
271 | 5 | nullptr; |
272 | 5 | } |
273 | | |
274 | | WatchpointEventType |
275 | 5 | SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) { |
276 | 5 | LLDB_INSTRUMENT_VA(event); |
277 | | |
278 | 5 | if (event.IsValid()) |
279 | 5 | return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent( |
280 | 5 | event.GetSP()); |
281 | 0 | return eWatchpointEventTypeInvalidType; |
282 | 5 | } |
283 | | |
284 | 0 | SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) { |
285 | 0 | LLDB_INSTRUMENT_VA(event); |
286 | |
|
287 | 0 | SBWatchpoint sb_watchpoint; |
288 | 0 | if (event.IsValid()) |
289 | 0 | sb_watchpoint = |
290 | 0 | Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP()); |
291 | 0 | return sb_watchpoint; |
292 | 0 | } |
293 | | |
294 | 6 | lldb::SBType SBWatchpoint::GetType() { |
295 | 6 | LLDB_INSTRUMENT_VA(this); |
296 | | |
297 | 6 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
298 | 6 | if (watchpoint_sp) { |
299 | 6 | std::lock_guard<std::recursive_mutex> guard( |
300 | 6 | watchpoint_sp->GetTarget().GetAPIMutex()); |
301 | 6 | const CompilerType &type = watchpoint_sp->GetCompilerType(); |
302 | 6 | return lldb::SBType(type); |
303 | 6 | } |
304 | 0 | return lldb::SBType(); |
305 | 6 | } |
306 | | |
307 | 3 | WatchpointValueKind SBWatchpoint::GetWatchValueKind() { |
308 | 3 | LLDB_INSTRUMENT_VA(this); |
309 | | |
310 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
311 | 3 | if (watchpoint_sp) { |
312 | 3 | std::lock_guard<std::recursive_mutex> guard( |
313 | 3 | watchpoint_sp->GetTarget().GetAPIMutex()); |
314 | 3 | if (watchpoint_sp->IsWatchVariable()) |
315 | 1 | return WatchpointValueKind::eWatchPointValueKindVariable; |
316 | 2 | return WatchpointValueKind::eWatchPointValueKindExpression; |
317 | 3 | } |
318 | 0 | return WatchpointValueKind::eWatchPointValueKindInvalid; |
319 | 3 | } |
320 | | |
321 | 5 | const char *SBWatchpoint::GetWatchSpec() { |
322 | 5 | LLDB_INSTRUMENT_VA(this); |
323 | | |
324 | 5 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
325 | 5 | if (!watchpoint_sp) |
326 | 0 | return nullptr; |
327 | | |
328 | 5 | std::lock_guard<std::recursive_mutex> guard( |
329 | 5 | watchpoint_sp->GetTarget().GetAPIMutex()); |
330 | | // Store the result of `GetWatchSpec()` as a ConstString |
331 | | // so that the C string we return has a sufficiently long |
332 | | // lifetime. Note this a memory leak but should be fairly |
333 | | // low impact. |
334 | 5 | return ConstString(watchpoint_sp->GetWatchSpec()).AsCString(); |
335 | 5 | } |
336 | | |
337 | 3 | bool SBWatchpoint::IsWatchingReads() { |
338 | 3 | LLDB_INSTRUMENT_VA(this); |
339 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
340 | 3 | if (watchpoint_sp) { |
341 | 3 | std::lock_guard<std::recursive_mutex> guard( |
342 | 3 | watchpoint_sp->GetTarget().GetAPIMutex()); |
343 | | |
344 | 3 | return watchpoint_sp->WatchpointRead(); |
345 | 3 | } |
346 | | |
347 | 0 | return false; |
348 | 3 | } |
349 | | |
350 | 3 | bool SBWatchpoint::IsWatchingWrites() { |
351 | 3 | LLDB_INSTRUMENT_VA(this); |
352 | 3 | lldb::WatchpointSP watchpoint_sp(GetSP()); |
353 | 3 | if (watchpoint_sp) { |
354 | 3 | std::lock_guard<std::recursive_mutex> guard( |
355 | 3 | watchpoint_sp->GetTarget().GetAPIMutex()); |
356 | | |
357 | 3 | return watchpoint_sp->WatchpointWrite() || |
358 | 3 | watchpoint_sp->WatchpointModify()1 ; |
359 | 3 | } |
360 | | |
361 | 0 | return false; |
362 | 3 | } |