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 "lldb/API/SBBroadcaster.h"
11 #include "lldb/API/SBDebugger.h"
12 #include "lldb/API/SBEvent.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/Core/Debugger.h"
15 #include "lldb/Utility/Broadcaster.h"
16 #include "lldb/Utility/Instrumentation.h"
17 #include "lldb/Utility/Listener.h"
18 #include "lldb/Utility/StreamString.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 SBListener::SBListener() { LLDB_INSTRUMENT_VA(this); }
24 
25 SBListener::SBListener(const char *name)
26     : m_opaque_sp(Listener::MakeListener(name)) {
27   LLDB_INSTRUMENT_VA(this, name);
28 }
29 
30 SBListener::SBListener(const SBListener &rhs) : m_opaque_sp(rhs.m_opaque_sp) {
31   LLDB_INSTRUMENT_VA(this, rhs);
32 }
33 
34 const lldb::SBListener &SBListener::operator=(const lldb::SBListener &rhs) {
35   LLDB_INSTRUMENT_VA(this, rhs);
36 
37   if (this != &rhs) {
38     m_opaque_sp = rhs.m_opaque_sp;
39     m_unused_ptr = nullptr;
40   }
41   return *this;
42 }
43 
44 SBListener::SBListener(const lldb::ListenerSP &listener_sp)
45     : m_opaque_sp(listener_sp) {}
46 
47 SBListener::~SBListener() = default;
48 
49 bool SBListener::IsValid() const {
50   LLDB_INSTRUMENT_VA(this);
51   return this->operator bool();
52 }
53 SBListener::operator bool() const {
54   LLDB_INSTRUMENT_VA(this);
55 
56   return m_opaque_sp != nullptr;
57 }
58 
59 void SBListener::AddEvent(const SBEvent &event) {
60   LLDB_INSTRUMENT_VA(this, event);
61 
62   EventSP &event_sp = event.GetSP();
63   if (event_sp)
64     m_opaque_sp->AddEvent(event_sp);
65 }
66 
67 void SBListener::Clear() {
68   LLDB_INSTRUMENT_VA(this);
69 
70   if (m_opaque_sp)
71     m_opaque_sp->Clear();
72 }
73 
74 uint32_t SBListener::StartListeningForEventClass(SBDebugger &debugger,
75                                                  const char *broadcaster_class,
76                                                  uint32_t event_mask) {
77   LLDB_INSTRUMENT_VA(this, debugger, broadcaster_class, event_mask);
78 
79   if (m_opaque_sp) {
80     Debugger *lldb_debugger = debugger.get();
81     if (!lldb_debugger)
82       return 0;
83     BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
84     return m_opaque_sp->StartListeningForEventSpec(
85         lldb_debugger->GetBroadcasterManager(), event_spec);
86   } else
87     return 0;
88 }
89 
90 bool SBListener::StopListeningForEventClass(SBDebugger &debugger,
91                                             const char *broadcaster_class,
92                                             uint32_t event_mask) {
93   LLDB_INSTRUMENT_VA(this, debugger, broadcaster_class, event_mask);
94 
95   if (m_opaque_sp) {
96     Debugger *lldb_debugger = debugger.get();
97     if (!lldb_debugger)
98       return false;
99     BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
100     return m_opaque_sp->StopListeningForEventSpec(
101         lldb_debugger->GetBroadcasterManager(), event_spec);
102   } else
103     return false;
104 }
105 
106 uint32_t SBListener::StartListeningForEvents(const SBBroadcaster &broadcaster,
107                                              uint32_t event_mask) {
108   LLDB_INSTRUMENT_VA(this, broadcaster, event_mask);
109 
110   uint32_t acquired_event_mask = 0;
111   if (m_opaque_sp && broadcaster.IsValid()) {
112     acquired_event_mask =
113         m_opaque_sp->StartListeningForEvents(broadcaster.get(), event_mask);
114   }
115 
116   return acquired_event_mask;
117 }
118 
119 bool SBListener::StopListeningForEvents(const SBBroadcaster &broadcaster,
120                                         uint32_t event_mask) {
121   LLDB_INSTRUMENT_VA(this, broadcaster, event_mask);
122 
123   if (m_opaque_sp && broadcaster.IsValid()) {
124     return m_opaque_sp->StopListeningForEvents(broadcaster.get(), event_mask);
125   }
126   return false;
127 }
128 
129 bool SBListener::WaitForEvent(uint32_t timeout_secs, SBEvent &event) {
130   LLDB_INSTRUMENT_VA(this, timeout_secs, event);
131 
132   bool success = false;
133 
134   if (m_opaque_sp) {
135     Timeout<std::micro> timeout(std::nullopt);
136     if (timeout_secs != UINT32_MAX) {
137       assert(timeout_secs != 0); // Take this out after all calls with timeout
138                                  // set to zero have been removed....
139       timeout = std::chrono::seconds(timeout_secs);
140     }
141     EventSP event_sp;
142     if (m_opaque_sp->GetEvent(event_sp, timeout)) {
143       event.reset(event_sp);
144       success = true;
145     }
146   }
147 
148   if (!success)
149     event.reset(nullptr);
150   return success;
151 }
152 
153 bool SBListener::WaitForEventForBroadcaster(uint32_t num_seconds,
154                                             const SBBroadcaster &broadcaster,
155                                             SBEvent &event) {
156   LLDB_INSTRUMENT_VA(this, num_seconds, broadcaster, event);
157 
158   if (m_opaque_sp && broadcaster.IsValid()) {
159     Timeout<std::micro> timeout(std::nullopt);
160     if (num_seconds != UINT32_MAX)
161       timeout = std::chrono::seconds(num_seconds);
162     EventSP event_sp;
163     if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
164                                             timeout)) {
165       event.reset(event_sp);
166       return true;
167     }
168   }
169   event.reset(nullptr);
170   return false;
171 }
172 
173 bool SBListener::WaitForEventForBroadcasterWithType(
174     uint32_t num_seconds, const SBBroadcaster &broadcaster,
175     uint32_t event_type_mask, SBEvent &event) {
176   LLDB_INSTRUMENT_VA(this, num_seconds, broadcaster, event_type_mask, event);
177 
178   if (m_opaque_sp && broadcaster.IsValid()) {
179     Timeout<std::micro> timeout(std::nullopt);
180     if (num_seconds != UINT32_MAX)
181       timeout = std::chrono::seconds(num_seconds);
182     EventSP event_sp;
183     if (m_opaque_sp->GetEventForBroadcasterWithType(
184             broadcaster.get(), event_type_mask, event_sp, timeout)) {
185       event.reset(event_sp);
186       return true;
187     }
188   }
189   event.reset(nullptr);
190   return false;
191 }
192 
193 bool SBListener::PeekAtNextEvent(SBEvent &event) {
194   LLDB_INSTRUMENT_VA(this, event);
195 
196   if (m_opaque_sp) {
197     event.reset(m_opaque_sp->PeekAtNextEvent());
198     return event.IsValid();
199   }
200   event.reset(nullptr);
201   return false;
202 }
203 
204 bool SBListener::PeekAtNextEventForBroadcaster(const SBBroadcaster &broadcaster,
205                                                SBEvent &event) {
206   LLDB_INSTRUMENT_VA(this, broadcaster, event);
207 
208   if (m_opaque_sp && broadcaster.IsValid()) {
209     event.reset(m_opaque_sp->PeekAtNextEventForBroadcaster(broadcaster.get()));
210     return event.IsValid();
211   }
212   event.reset(nullptr);
213   return false;
214 }
215 
216 bool SBListener::PeekAtNextEventForBroadcasterWithType(
217     const SBBroadcaster &broadcaster, uint32_t event_type_mask,
218     SBEvent &event) {
219   LLDB_INSTRUMENT_VA(this, broadcaster, event_type_mask, event);
220 
221   if (m_opaque_sp && broadcaster.IsValid()) {
222     event.reset(m_opaque_sp->PeekAtNextEventForBroadcasterWithType(
223         broadcaster.get(), event_type_mask));
224     return event.IsValid();
225   }
226   event.reset(nullptr);
227   return false;
228 }
229 
230 bool SBListener::GetNextEvent(SBEvent &event) {
231   LLDB_INSTRUMENT_VA(this, event);
232 
233   if (m_opaque_sp) {
234     EventSP event_sp;
235     if (m_opaque_sp->GetEvent(event_sp, std::chrono::seconds(0))) {
236       event.reset(event_sp);
237       return true;
238     }
239   }
240   event.reset(nullptr);
241   return false;
242 }
243 
244 bool SBListener::GetNextEventForBroadcaster(const SBBroadcaster &broadcaster,
245                                             SBEvent &event) {
246   LLDB_INSTRUMENT_VA(this, broadcaster, event);
247 
248   if (m_opaque_sp && broadcaster.IsValid()) {
249     EventSP event_sp;
250     if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
251                                             std::chrono::seconds(0))) {
252       event.reset(event_sp);
253       return true;
254     }
255   }
256   event.reset(nullptr);
257   return false;
258 }
259 
260 bool SBListener::GetNextEventForBroadcasterWithType(
261     const SBBroadcaster &broadcaster, uint32_t event_type_mask,
262     SBEvent &event) {
263   LLDB_INSTRUMENT_VA(this, broadcaster, event_type_mask, event);
264 
265   if (m_opaque_sp && broadcaster.IsValid()) {
266     EventSP event_sp;
267     if (m_opaque_sp->GetEventForBroadcasterWithType(broadcaster.get(),
268                                                     event_type_mask, event_sp,
269                                                     std::chrono::seconds(0))) {
270       event.reset(event_sp);
271       return true;
272     }
273   }
274   event.reset(nullptr);
275   return false;
276 }
277 
278 bool SBListener::HandleBroadcastEvent(const SBEvent &event) {
279   LLDB_INSTRUMENT_VA(this, event);
280 
281   if (m_opaque_sp)
282     return m_opaque_sp->HandleBroadcastEvent(event.GetSP());
283   return false;
284 }
285 
286 lldb::ListenerSP SBListener::GetSP() { return m_opaque_sp; }
287 
288 Listener *SBListener::operator->() const { return m_opaque_sp.get(); }
289 
290 Listener *SBListener::get() const { return m_opaque_sp.get(); }
291 
292 void SBListener::reset(ListenerSP listener_sp) {
293   m_opaque_sp = listener_sp;
294   m_unused_ptr = nullptr;
295 }
296