1//===-- Event.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/Utility/Event.h"
10
11#include "lldb/Utility/Broadcaster.h"
12#include "lldb/Utility/DataExtractor.h"
13#include "lldb/Utility/Endian.h"
14#include "lldb/Utility/Listener.h"
15#include "lldb/Utility/Stream.h"
16#include "lldb/Utility/StreamString.h"
17#include "lldb/lldb-enumerations.h"
18
19#include "llvm/ADT/StringExtras.h"
20
21#include <algorithm>
22
23#include <cctype>
24
25using namespace lldb;
26using namespace lldb_private;
27
28#pragma mark -
29#pragma mark Event
30
31// Event functions
32
33Event::Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data)
34    : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type),
35      m_data_sp(data) {}
36
37Event::Event(Broadcaster *broadcaster, uint32_t event_type,
38             const EventDataSP &event_data_sp)
39    : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type),
40      m_data_sp(event_data_sp) {}
41
42Event::Event(uint32_t event_type, EventData *data)
43    : m_broadcaster_wp(), m_type(event_type), m_data_sp(data) {}
44
45Event::Event(uint32_t event_type, const EventDataSP &event_data_sp)
46    : m_broadcaster_wp(), m_type(event_type), m_data_sp(event_data_sp) {}
47
48Event::~Event() = default;
49
50void Event::Dump(Stream *s) const {
51  Broadcaster *broadcaster;
52  Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock());
53  if (broadcaster_impl_sp)
54    broadcaster = broadcaster_impl_sp->GetBroadcaster();
55  else
56    broadcaster = nullptr;
57
58  if (broadcaster) {
59    StreamString event_name;
60    if (broadcaster->GetEventNames(event_name, m_type, false))
61      s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ",
62                static_cast<const void *>(this),
63                static_cast<void *>(broadcaster),
64                broadcaster->GetBroadcasterName().c_str(), m_type,
65                event_name.GetData());
66    else
67      s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ",
68                static_cast<const void *>(this),
69                static_cast<void *>(broadcaster),
70                broadcaster->GetBroadcasterName().c_str(), m_type);
71  } else
72    s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ",
73              static_cast<const void *>(this), m_type);
74
75  if (m_data_sp) {
76    s->PutChar('{');
77    m_data_sp->Dump(s);
78    s->PutChar('}');
79  } else
80    s->Printf("<NULL>");
81}
82
83void Event::DoOnRemoval() {
84  std::lock_guard<std::mutex> guard(m_listeners_mutex);
85
86  if (m_data_sp)
87    m_data_sp->DoOnRemoval(this);
88  // Now that the event has been handled by the primary event Listener, forward
89  // it to the other Listeners.
90  EventSP me_sp = shared_from_this();
91  for (auto listener_sp : m_pending_listeners)
92    listener_sp->AddEvent(me_sp);
93  m_pending_listeners.clear();
94}
95
96#pragma mark -
97#pragma mark EventData
98
99// EventData functions
100
101EventData::EventData() = default;
102
103EventData::~EventData() = default;
104
105void EventData::Dump(Stream *s) const { s->PutCString("Generic Event Data"); }
106
107#pragma mark -
108#pragma mark EventDataBytes
109
110// EventDataBytes functions
111
112EventDataBytes::EventDataBytes() : m_bytes() {}
113
114EventDataBytes::EventDataBytes(const char *cstr) : m_bytes() {
115  SetBytesFromCString(cstr);
116}
117
118EventDataBytes::EventDataBytes(llvm::StringRef str) : m_bytes() {
119  SetBytes(str.data(), str.size());
120}
121
122EventDataBytes::EventDataBytes(const void *src, size_t src_len) : m_bytes() {
123  SetBytes(src, src_len);
124}
125
126EventDataBytes::~EventDataBytes() = default;
127
128llvm::StringRef EventDataBytes::GetFlavorString() { return "EventDataBytes"; }
129
130llvm::StringRef EventDataBytes::GetFlavor() const {
131  return EventDataBytes::GetFlavorString();
132}
133
134void EventDataBytes::Dump(Stream *s) const {
135  if (llvm::all_of(m_bytes, llvm::isPrint))
136    s->Format("\"{0}\"", m_bytes);
137  else
138    s->Format("{0:$[ ]@[x-2]}", llvm::make_range(
139                         reinterpret_cast<const uint8_t *>(m_bytes.data()),
140                         reinterpret_cast<const uint8_t *>(m_bytes.data() +
141                                                           m_bytes.size())));
142}
143
144const void *EventDataBytes::GetBytes() const {
145  return (m_bytes.empty() ? nullptr : m_bytes.data());
146}
147
148size_t EventDataBytes::GetByteSize() const { return m_bytes.size(); }
149
150void EventDataBytes::SetBytes(const void *src, size_t src_len) {
151  if (src != nullptr && src_len > 0)
152    m_bytes.assign(static_cast<const char *>(src), src_len);
153  else
154    m_bytes.clear();
155}
156
157void EventDataBytes::SetBytesFromCString(const char *cstr) {
158  if (cstr != nullptr && cstr[0])
159    m_bytes.assign(cstr);
160  else
161    m_bytes.clear();
162}
163
164const void *EventDataBytes::GetBytesFromEvent(const Event *event_ptr) {
165  const EventDataBytes *e = GetEventDataFromEvent(event_ptr);
166  if (e != nullptr)
167    return e->GetBytes();
168  return nullptr;
169}
170
171size_t EventDataBytes::GetByteSizeFromEvent(const Event *event_ptr) {
172  const EventDataBytes *e = GetEventDataFromEvent(event_ptr);
173  if (e != nullptr)
174    return e->GetByteSize();
175  return 0;
176}
177
178const EventDataBytes *
179EventDataBytes::GetEventDataFromEvent(const Event *event_ptr) {
180  if (event_ptr != nullptr) {
181    const EventData *event_data = event_ptr->GetData();
182    if (event_data &&
183        event_data->GetFlavor() == EventDataBytes::GetFlavorString())
184      return static_cast<const EventDataBytes *>(event_data);
185  }
186  return nullptr;
187}
188
189void EventDataBytes::SwapBytes(std::string &new_bytes) {
190  m_bytes.swap(new_bytes);
191}
192
193llvm::StringRef EventDataReceipt::GetFlavorString() {
194  return "Process::ProcessEventData";
195}
196
197#pragma mark -
198#pragma mark EventStructuredData
199
200// EventDataStructuredData definitions
201
202EventDataStructuredData::EventDataStructuredData()
203    : EventData(), m_process_sp(), m_object_sp(), m_plugin_sp() {}
204
205EventDataStructuredData::EventDataStructuredData(
206    const ProcessSP &process_sp, const StructuredData::ObjectSP &object_sp,
207    const lldb::StructuredDataPluginSP &plugin_sp)
208    : EventData(), m_process_sp(process_sp), m_object_sp(object_sp),
209      m_plugin_sp(plugin_sp) {}
210
211EventDataStructuredData::~EventDataStructuredData() = default;
212
213// EventDataStructuredData member functions
214
215llvm::StringRef EventDataStructuredData::GetFlavor() const {
216  return EventDataStructuredData::GetFlavorString();
217}
218
219void EventDataStructuredData::Dump(Stream *s) const {
220  if (!s)
221    return;
222
223  if (m_object_sp)
224    m_object_sp->Dump(*s);
225}
226
227const ProcessSP &EventDataStructuredData::GetProcess() const {
228  return m_process_sp;
229}
230
231const StructuredData::ObjectSP &EventDataStructuredData::GetObject() const {
232  return m_object_sp;
233}
234
235const lldb::StructuredDataPluginSP &
236EventDataStructuredData::GetStructuredDataPlugin() const {
237  return m_plugin_sp;
238}
239
240void EventDataStructuredData::SetProcess(const ProcessSP &process_sp) {
241  m_process_sp = process_sp;
242}
243
244void EventDataStructuredData::SetObject(
245    const StructuredData::ObjectSP &object_sp) {
246  m_object_sp = object_sp;
247}
248
249void EventDataStructuredData::SetStructuredDataPlugin(
250    const lldb::StructuredDataPluginSP &plugin_sp) {
251  m_plugin_sp = plugin_sp;
252}
253
254// EventDataStructuredData static functions
255
256const EventDataStructuredData *
257EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr) {
258  if (event_ptr == nullptr)
259    return nullptr;
260
261  const EventData *event_data = event_ptr->GetData();
262  if (!event_data ||
263      event_data->GetFlavor() != EventDataStructuredData::GetFlavorString())
264    return nullptr;
265
266  return static_cast<const EventDataStructuredData *>(event_data);
267}
268
269ProcessSP EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr) {
270  auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
271  if (event_data)
272    return event_data->GetProcess();
273  else
274    return ProcessSP();
275}
276
277StructuredData::ObjectSP
278EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr) {
279  auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
280  if (event_data)
281    return event_data->GetObject();
282  else
283    return StructuredData::ObjectSP();
284}
285
286lldb::StructuredDataPluginSP
287EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr) {
288  auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
289  if (event_data)
290    return event_data->GetStructuredDataPlugin();
291  else
292    return StructuredDataPluginSP();
293}
294
295llvm::StringRef EventDataStructuredData::GetFlavorString() {
296  return "EventDataStructuredData";
297}
298