1 //===-- SBListener.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/SBListener.h"
10 #include "SBReproducerPrivate.h"
11 #include "lldb/API/SBBroadcaster.h"
12 #include "lldb/API/SBDebugger.h"
13 #include "lldb/API/SBEvent.h"
14 #include "lldb/API/SBStream.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Utility/Broadcaster.h"
17 #include "lldb/Utility/Listener.h"
18 #include "lldb/Utility/StreamString.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
SBListener()23 SBListener::SBListener() : m_opaque_sp(), m_unused_ptr(nullptr) {
24 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBListener);
25 }
26
SBListener(const char * name)27 SBListener::SBListener(const char *name)
28 : m_opaque_sp(Listener::MakeListener(name)), m_unused_ptr(nullptr) {
29 LLDB_RECORD_CONSTRUCTOR(SBListener, (const char *), name);
30 }
31
SBListener(const SBListener & rhs)32 SBListener::SBListener(const SBListener &rhs)
33 : m_opaque_sp(rhs.m_opaque_sp), m_unused_ptr(nullptr) {
34 LLDB_RECORD_CONSTRUCTOR(SBListener, (const lldb::SBListener &), rhs);
35 }
36
operator =(const lldb::SBListener & rhs)37 const lldb::SBListener &SBListener::operator=(const lldb::SBListener &rhs) {
38 LLDB_RECORD_METHOD(const lldb::SBListener &,
39 SBListener, operator=,(const lldb::SBListener &), rhs);
40
41 if (this != &rhs) {
42 m_opaque_sp = rhs.m_opaque_sp;
43 m_unused_ptr = nullptr;
44 }
45 return LLDB_RECORD_RESULT(*this);
46 }
47
SBListener(const lldb::ListenerSP & listener_sp)48 SBListener::SBListener(const lldb::ListenerSP &listener_sp)
49 : m_opaque_sp(listener_sp), m_unused_ptr(nullptr) {}
50
51 SBListener::~SBListener() = default;
52
IsValid() const53 bool SBListener::IsValid() const {
54 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBListener, IsValid);
55 return this->operator bool();
56 }
operator bool() const57 SBListener::operator bool() const {
58 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBListener, operator bool);
59
60 return m_opaque_sp != nullptr;
61 }
62
AddEvent(const SBEvent & event)63 void SBListener::AddEvent(const SBEvent &event) {
64 LLDB_RECORD_METHOD(void, SBListener, AddEvent, (const lldb::SBEvent &),
65 event);
66
67 EventSP &event_sp = event.GetSP();
68 if (event_sp)
69 m_opaque_sp->AddEvent(event_sp);
70 }
71
Clear()72 void SBListener::Clear() {
73 LLDB_RECORD_METHOD_NO_ARGS(void, SBListener, Clear);
74
75 if (m_opaque_sp)
76 m_opaque_sp->Clear();
77 }
78
StartListeningForEventClass(SBDebugger & debugger,const char * broadcaster_class,uint32_t event_mask)79 uint32_t SBListener::StartListeningForEventClass(SBDebugger &debugger,
80 const char *broadcaster_class,
81 uint32_t event_mask) {
82 LLDB_RECORD_METHOD(uint32_t, SBListener, StartListeningForEventClass,
83 (lldb::SBDebugger &, const char *, uint32_t), debugger,
84 broadcaster_class, event_mask);
85
86 if (m_opaque_sp) {
87 Debugger *lldb_debugger = debugger.get();
88 if (!lldb_debugger)
89 return 0;
90 BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
91 return m_opaque_sp->StartListeningForEventSpec(
92 lldb_debugger->GetBroadcasterManager(), event_spec);
93 } else
94 return 0;
95 }
96
StopListeningForEventClass(SBDebugger & debugger,const char * broadcaster_class,uint32_t event_mask)97 bool SBListener::StopListeningForEventClass(SBDebugger &debugger,
98 const char *broadcaster_class,
99 uint32_t event_mask) {
100 LLDB_RECORD_METHOD(bool, SBListener, StopListeningForEventClass,
101 (lldb::SBDebugger &, const char *, uint32_t), debugger,
102 broadcaster_class, event_mask);
103
104 if (m_opaque_sp) {
105 Debugger *lldb_debugger = debugger.get();
106 if (!lldb_debugger)
107 return false;
108 BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
109 return m_opaque_sp->StopListeningForEventSpec(
110 lldb_debugger->GetBroadcasterManager(), event_spec);
111 } else
112 return false;
113 }
114
StartListeningForEvents(const SBBroadcaster & broadcaster,uint32_t event_mask)115 uint32_t SBListener::StartListeningForEvents(const SBBroadcaster &broadcaster,
116 uint32_t event_mask) {
117 LLDB_RECORD_METHOD(uint32_t, SBListener, StartListeningForEvents,
118 (const lldb::SBBroadcaster &, uint32_t), broadcaster,
119 event_mask);
120
121 uint32_t acquired_event_mask = 0;
122 if (m_opaque_sp && broadcaster.IsValid()) {
123 acquired_event_mask =
124 m_opaque_sp->StartListeningForEvents(broadcaster.get(), event_mask);
125 }
126
127 return acquired_event_mask;
128 }
129
StopListeningForEvents(const SBBroadcaster & broadcaster,uint32_t event_mask)130 bool SBListener::StopListeningForEvents(const SBBroadcaster &broadcaster,
131 uint32_t event_mask) {
132 LLDB_RECORD_METHOD(bool, SBListener, StopListeningForEvents,
133 (const lldb::SBBroadcaster &, uint32_t), broadcaster,
134 event_mask);
135
136 if (m_opaque_sp && broadcaster.IsValid()) {
137 return m_opaque_sp->StopListeningForEvents(broadcaster.get(), event_mask);
138 }
139 return false;
140 }
141
WaitForEvent(uint32_t timeout_secs,SBEvent & event)142 bool SBListener::WaitForEvent(uint32_t timeout_secs, SBEvent &event) {
143 LLDB_RECORD_METHOD(bool, SBListener, WaitForEvent,
144 (uint32_t, lldb::SBEvent &), timeout_secs, event);
145
146 bool success = false;
147
148 if (m_opaque_sp) {
149 Timeout<std::micro> timeout(llvm::None);
150 if (timeout_secs != UINT32_MAX) {
151 assert(timeout_secs != 0); // Take this out after all calls with timeout
152 // set to zero have been removed....
153 timeout = std::chrono::seconds(timeout_secs);
154 }
155 EventSP event_sp;
156 if (m_opaque_sp->GetEvent(event_sp, timeout)) {
157 event.reset(event_sp);
158 success = true;
159 }
160 }
161
162 if (!success)
163 event.reset(nullptr);
164 return success;
165 }
166
WaitForEventForBroadcaster(uint32_t num_seconds,const SBBroadcaster & broadcaster,SBEvent & event)167 bool SBListener::WaitForEventForBroadcaster(uint32_t num_seconds,
168 const SBBroadcaster &broadcaster,
169 SBEvent &event) {
170 LLDB_RECORD_METHOD(bool, SBListener, WaitForEventForBroadcaster,
171 (uint32_t, const lldb::SBBroadcaster &, lldb::SBEvent &),
172 num_seconds, broadcaster, event);
173
174 if (m_opaque_sp && broadcaster.IsValid()) {
175 Timeout<std::micro> timeout(llvm::None);
176 if (num_seconds != UINT32_MAX)
177 timeout = std::chrono::seconds(num_seconds);
178 EventSP event_sp;
179 if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
180 timeout)) {
181 event.reset(event_sp);
182 return true;
183 }
184 }
185 event.reset(nullptr);
186 return false;
187 }
188
WaitForEventForBroadcasterWithType(uint32_t num_seconds,const SBBroadcaster & broadcaster,uint32_t event_type_mask,SBEvent & event)189 bool SBListener::WaitForEventForBroadcasterWithType(
190 uint32_t num_seconds, const SBBroadcaster &broadcaster,
191 uint32_t event_type_mask, SBEvent &event) {
192 LLDB_RECORD_METHOD(
193 bool, SBListener, WaitForEventForBroadcasterWithType,
194 (uint32_t, const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
195 num_seconds, broadcaster, event_type_mask, event);
196
197 if (m_opaque_sp && broadcaster.IsValid()) {
198 Timeout<std::micro> timeout(llvm::None);
199 if (num_seconds != UINT32_MAX)
200 timeout = std::chrono::seconds(num_seconds);
201 EventSP event_sp;
202 if (m_opaque_sp->GetEventForBroadcasterWithType(
203 broadcaster.get(), event_type_mask, event_sp, timeout)) {
204 event.reset(event_sp);
205 return true;
206 }
207 }
208 event.reset(nullptr);
209 return false;
210 }
211
PeekAtNextEvent(SBEvent & event)212 bool SBListener::PeekAtNextEvent(SBEvent &event) {
213 LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEvent, (lldb::SBEvent &),
214 event);
215
216 if (m_opaque_sp) {
217 event.reset(m_opaque_sp->PeekAtNextEvent());
218 return event.IsValid();
219 }
220 event.reset(nullptr);
221 return false;
222 }
223
PeekAtNextEventForBroadcaster(const SBBroadcaster & broadcaster,SBEvent & event)224 bool SBListener::PeekAtNextEventForBroadcaster(const SBBroadcaster &broadcaster,
225 SBEvent &event) {
226 LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEventForBroadcaster,
227 (const lldb::SBBroadcaster &, lldb::SBEvent &),
228 broadcaster, event);
229
230 if (m_opaque_sp && broadcaster.IsValid()) {
231 event.reset(m_opaque_sp->PeekAtNextEventForBroadcaster(broadcaster.get()));
232 return event.IsValid();
233 }
234 event.reset(nullptr);
235 return false;
236 }
237
PeekAtNextEventForBroadcasterWithType(const SBBroadcaster & broadcaster,uint32_t event_type_mask,SBEvent & event)238 bool SBListener::PeekAtNextEventForBroadcasterWithType(
239 const SBBroadcaster &broadcaster, uint32_t event_type_mask,
240 SBEvent &event) {
241 LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEventForBroadcasterWithType,
242 (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
243 broadcaster, event_type_mask, event);
244
245 if (m_opaque_sp && broadcaster.IsValid()) {
246 event.reset(m_opaque_sp->PeekAtNextEventForBroadcasterWithType(
247 broadcaster.get(), event_type_mask));
248 return event.IsValid();
249 }
250 event.reset(nullptr);
251 return false;
252 }
253
GetNextEvent(SBEvent & event)254 bool SBListener::GetNextEvent(SBEvent &event) {
255 LLDB_RECORD_METHOD(bool, SBListener, GetNextEvent, (lldb::SBEvent &), event);
256
257 if (m_opaque_sp) {
258 EventSP event_sp;
259 if (m_opaque_sp->GetEvent(event_sp, std::chrono::seconds(0))) {
260 event.reset(event_sp);
261 return true;
262 }
263 }
264 event.reset(nullptr);
265 return false;
266 }
267
GetNextEventForBroadcaster(const SBBroadcaster & broadcaster,SBEvent & event)268 bool SBListener::GetNextEventForBroadcaster(const SBBroadcaster &broadcaster,
269 SBEvent &event) {
270 LLDB_RECORD_METHOD(bool, SBListener, GetNextEventForBroadcaster,
271 (const lldb::SBBroadcaster &, lldb::SBEvent &),
272 broadcaster, event);
273
274 if (m_opaque_sp && broadcaster.IsValid()) {
275 EventSP event_sp;
276 if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
277 std::chrono::seconds(0))) {
278 event.reset(event_sp);
279 return true;
280 }
281 }
282 event.reset(nullptr);
283 return false;
284 }
285
GetNextEventForBroadcasterWithType(const SBBroadcaster & broadcaster,uint32_t event_type_mask,SBEvent & event)286 bool SBListener::GetNextEventForBroadcasterWithType(
287 const SBBroadcaster &broadcaster, uint32_t event_type_mask,
288 SBEvent &event) {
289 LLDB_RECORD_METHOD(bool, SBListener, GetNextEventForBroadcasterWithType,
290 (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
291 broadcaster, event_type_mask, event);
292
293 if (m_opaque_sp && broadcaster.IsValid()) {
294 EventSP event_sp;
295 if (m_opaque_sp->GetEventForBroadcasterWithType(broadcaster.get(),
296 event_type_mask, event_sp,
297 std::chrono::seconds(0))) {
298 event.reset(event_sp);
299 return true;
300 }
301 }
302 event.reset(nullptr);
303 return false;
304 }
305
HandleBroadcastEvent(const SBEvent & event)306 bool SBListener::HandleBroadcastEvent(const SBEvent &event) {
307 LLDB_RECORD_METHOD(bool, SBListener, HandleBroadcastEvent,
308 (const lldb::SBEvent &), event);
309
310 if (m_opaque_sp)
311 return m_opaque_sp->HandleBroadcastEvent(event.GetSP());
312 return false;
313 }
314
GetSP()315 lldb::ListenerSP SBListener::GetSP() { return m_opaque_sp; }
316
operator ->() const317 Listener *SBListener::operator->() const { return m_opaque_sp.get(); }
318
get() const319 Listener *SBListener::get() const { return m_opaque_sp.get(); }
320
reset(ListenerSP listener_sp)321 void SBListener::reset(ListenerSP listener_sp) {
322 m_opaque_sp = listener_sp;
323 m_unused_ptr = nullptr;
324 }
325
326 namespace lldb_private {
327 namespace repro {
328
329 template <>
RegisterMethods(Registry & R)330 void RegisterMethods<SBListener>(Registry &R) {
331 LLDB_REGISTER_CONSTRUCTOR(SBListener, ());
332 LLDB_REGISTER_CONSTRUCTOR(SBListener, (const char *));
333 LLDB_REGISTER_CONSTRUCTOR(SBListener, (const lldb::SBListener &));
334 LLDB_REGISTER_METHOD(const lldb::SBListener &,
335 SBListener, operator=,(const lldb::SBListener &));
336 LLDB_REGISTER_METHOD_CONST(bool, SBListener, IsValid, ());
337 LLDB_REGISTER_METHOD_CONST(bool, SBListener, operator bool, ());
338 LLDB_REGISTER_METHOD(void, SBListener, AddEvent, (const lldb::SBEvent &));
339 LLDB_REGISTER_METHOD(void, SBListener, Clear, ());
340 LLDB_REGISTER_METHOD(uint32_t, SBListener, StartListeningForEventClass,
341 (lldb::SBDebugger &, const char *, uint32_t));
342 LLDB_REGISTER_METHOD(bool, SBListener, StopListeningForEventClass,
343 (lldb::SBDebugger &, const char *, uint32_t));
344 LLDB_REGISTER_METHOD(uint32_t, SBListener, StartListeningForEvents,
345 (const lldb::SBBroadcaster &, uint32_t));
346 LLDB_REGISTER_METHOD(bool, SBListener, StopListeningForEvents,
347 (const lldb::SBBroadcaster &, uint32_t));
348 LLDB_REGISTER_METHOD(bool, SBListener, WaitForEvent,
349 (uint32_t, lldb::SBEvent &));
350 LLDB_REGISTER_METHOD(
351 bool, SBListener, WaitForEventForBroadcaster,
352 (uint32_t, const lldb::SBBroadcaster &, lldb::SBEvent &));
353 LLDB_REGISTER_METHOD(
354 bool, SBListener, WaitForEventForBroadcasterWithType,
355 (uint32_t, const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
356 LLDB_REGISTER_METHOD(bool, SBListener, PeekAtNextEvent, (lldb::SBEvent &));
357 LLDB_REGISTER_METHOD(bool, SBListener, PeekAtNextEventForBroadcaster,
358 (const lldb::SBBroadcaster &, lldb::SBEvent &));
359 LLDB_REGISTER_METHOD(
360 bool, SBListener, PeekAtNextEventForBroadcasterWithType,
361 (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
362 LLDB_REGISTER_METHOD(bool, SBListener, GetNextEvent, (lldb::SBEvent &));
363 LLDB_REGISTER_METHOD(bool, SBListener, GetNextEventForBroadcaster,
364 (const lldb::SBBroadcaster &, lldb::SBEvent &));
365 LLDB_REGISTER_METHOD(
366 bool, SBListener, GetNextEventForBroadcasterWithType,
367 (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
368 LLDB_REGISTER_METHOD(bool, SBListener, HandleBroadcastEvent,
369 (const lldb::SBEvent &));
370 }
371
372 }
373 }
374