Skip to content

Commit e0cc8db

Browse files
committed
[lldb/Utility] Add opt-in shadow mode to event listeners
This patch augments lldb's event listeners with a new shadow mode. As the name suggests, this mode allows events to be copied to an additional listener to perform event monitoring, without interferring with the event life cycle. One of our use case for this, is to be able to listen to public process events while making sure the events will still be delivered to the default process listener (the debugger listener in most cases). Differential Revision: https://reviews.llvm.org/D148397 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 4bb4a65 commit e0cc8db

File tree

16 files changed

+129
-4
lines changed

16 files changed

+129
-4
lines changed

lldb/bindings/interface/SBAttachInfo.i

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ public:
113113
void
114114
SetListener (lldb::SBListener &listener);
115115

116+
SBListener
117+
GetShadowListener();
118+
119+
void
120+
SetShadowListener(SBListener &listener);
121+
116122
const char *
117123
GetScriptedProcessClassName() const;
118124

lldb/bindings/interface/SBLaunchInfo.i

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ public:
4949
void
5050
SetListener (lldb::SBListener &listener);
5151

52+
SBListener
53+
GetShadowListener();
54+
55+
void
56+
SetShadowListener(SBListener &listener);
57+
5258
uint32_t
5359
GetNumArguments ();
5460

lldb/include/lldb/API/SBAttachInfo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,25 @@ class LLDB_API SBAttachInfo {
168168
/// allows a different listener to be used to listen for process events.
169169
void SetListener(SBListener &listener);
170170

171+
/// Get the shadow listener that receive public process events,
172+
/// additionally to the default process event listener.
173+
///
174+
/// If no listener has been set via a call to
175+
/// SBLaunchInfo::SetShadowListener(), then an invalid SBListener will
176+
/// be returned (SBListener::IsValid() will return false). If a listener
177+
/// has been set, then the valid listener object will be returned.
178+
SBListener GetShadowListener();
179+
180+
/// Set the shadow listener that will receive public process events,
181+
/// additionally to the default process event listener.
182+
///
183+
/// By default a process have no shadow event listener.
184+
/// Calling this function allows public process events to be broadcasted to an
185+
/// additional listener on top of the default process event listener.
186+
/// If the `listener` argument is invalid (SBListener::IsValid() will
187+
/// return false), this will clear the shadow listener.
188+
void SetShadowListener(SBListener &listener);
189+
171190
const char *GetScriptedProcessClassName() const;
172191

173192
void SetScriptedProcessClassName(const char *class_name);

lldb/include/lldb/API/SBLaunchInfo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,25 @@ class LLDB_API SBLaunchInfo {
8585
/// allows a different listener to be used to listen for process events.
8686
void SetListener(SBListener &listener);
8787

88+
/// Get the shadow listener that receive public process events,
89+
/// additionally to the default process event listener.
90+
///
91+
/// If no listener has been set via a call to
92+
/// SBLaunchInfo::SetShadowListener(), then an invalid SBListener will
93+
/// be returned (SBListener::IsValid() will return false). If a listener
94+
/// has been set, then the valid listener object will be returned.
95+
SBListener GetShadowListener();
96+
97+
/// Set the shadow listener that will receive public process events,
98+
/// additionally to the default process event listener.
99+
///
100+
/// By default a process have no shadow event listener.
101+
/// Calling this function allows public process events to be broadcasted to an
102+
/// additional listener on top of the default process event listener.
103+
/// If the `listener` argument is invalid (SBListener::IsValid() will
104+
/// return false), this will clear the shadow listener.
105+
void SetShadowListener(SBListener &listener);
106+
88107
uint32_t GetNumArguments();
89108

90109
const char *GetArgumentAtIndex(uint32_t idx);

lldb/include/lldb/Target/Process.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ class Process : public std::enable_shared_from_this<Process>,
383383
return GetStaticBroadcasterClass();
384384
}
385385

386+
void SetShadowListener(lldb::ListenerSP listener_sp) override {
387+
Broadcaster::SetShadowListener(listener_sp);
388+
}
389+
386390
/// A notification structure that can be used by clients to listen
387391
/// for changes in a process's lifetime.
388392
///

lldb/include/lldb/Utility/Broadcaster.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ class Broadcaster {
406406

407407
lldb::BroadcasterManagerSP GetManager();
408408

409+
virtual void SetShadowListener(lldb::ListenerSP listener_sp) {
410+
m_broadcaster_sp->m_shadow_listener = listener_sp;
411+
}
412+
409413
protected:
410414
/// BroadcasterImpl contains the actual Broadcaster implementation. The
411415
/// Broadcaster makes a BroadcasterImpl which lives as long as it does. The
@@ -513,6 +517,10 @@ class Broadcaster {
513517
/// for now this is just for private hijacking.
514518
std::vector<uint32_t> m_hijacking_masks;
515519

520+
/// A optional listener that all private events get also broadcasted to,
521+
/// on top the hijacked / default listeners.
522+
lldb::ListenerSP m_shadow_listener = nullptr;
523+
516524
private:
517525
BroadcasterImpl(const BroadcasterImpl &) = delete;
518526
const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete;

lldb/include/lldb/Utility/Listener.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class Listener : public std::enable_shared_from_this<Listener> {
9595

9696
size_t HandleBroadcastEvent(lldb::EventSP &event_sp);
9797

98+
void SetShadow(bool is_shadow) { m_is_shadow = is_shadow; }
99+
98100
private:
99101
// Classes that inherit from Listener can see and modify these
100102
struct BroadcasterInfo {
@@ -134,6 +136,7 @@ class Listener : public std::enable_shared_from_this<Listener> {
134136
std::mutex m_events_mutex; // Protects m_broadcasters and m_events
135137
std::condition_variable m_events_condition;
136138
broadcaster_manager_collection m_broadcaster_managers;
139+
bool m_is_shadow = false;
137140

138141
void BroadcasterWillDestruct(Broadcaster *);
139142

lldb/include/lldb/Utility/ProcessInfo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ class ProcessInfo {
110110
m_hijack_listener_sp = listener_sp;
111111
}
112112

113+
lldb::ListenerSP GetShadowListener() const { return m_shadow_listener_sp; }
114+
115+
void SetShadowListener(const lldb::ListenerSP &listener_sp) {
116+
m_shadow_listener_sp = listener_sp;
117+
}
118+
113119
protected:
114120
FileSpec m_executable;
115121
std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
@@ -124,6 +130,7 @@ class ProcessInfo {
124130
lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
125131
lldb::ListenerSP m_listener_sp = nullptr;
126132
lldb::ListenerSP m_hijack_listener_sp = nullptr;
133+
lldb::ListenerSP m_shadow_listener_sp = nullptr;
127134
};
128135

129136
// ProcessInstanceInfo

lldb/source/API/SBAttachInfo.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,27 @@ void SBAttachInfo::SetListener(SBListener &listener) {
254254
m_opaque_sp->SetListener(listener.GetSP());
255255
}
256256

257+
SBListener SBAttachInfo::GetShadowListener() {
258+
LLDB_INSTRUMENT_VA(this);
259+
260+
lldb::ListenerSP shadow_sp = m_opaque_sp->GetShadowListener();
261+
if (!shadow_sp)
262+
return SBListener();
263+
return SBListener(shadow_sp);
264+
}
265+
266+
void SBAttachInfo::SetShadowListener(SBListener &listener) {
267+
LLDB_INSTRUMENT_VA(this, listener);
268+
269+
ListenerSP listener_sp = listener.GetSP();
270+
if (listener_sp && listener.IsValid())
271+
listener_sp->SetShadow(true);
272+
else
273+
listener_sp = nullptr;
274+
275+
m_opaque_sp->SetShadowListener(listener_sp);
276+
}
277+
257278
const char *SBAttachInfo::GetScriptedProcessClassName() const {
258279
LLDB_INSTRUMENT_VA(this);
259280

lldb/source/API/SBLaunchInfo.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "lldb/API/SBStructuredData.h"
1818
#include "lldb/Core/StructuredDataImpl.h"
1919
#include "lldb/Host/ProcessLaunchInfo.h"
20+
#include "lldb/Utility/Listener.h"
2021
#include "lldb/Utility/ScriptedMetadata.h"
2122

2223
using namespace lldb;
@@ -387,3 +388,24 @@ void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
387388
metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
388389
m_opaque_sp->SetScriptedMetadata(metadata_sp);
389390
}
391+
392+
SBListener SBLaunchInfo::GetShadowListener() {
393+
LLDB_INSTRUMENT_VA(this);
394+
395+
lldb::ListenerSP shadow_sp = m_opaque_sp->GetShadowListener();
396+
if (!shadow_sp)
397+
return SBListener();
398+
return SBListener(shadow_sp);
399+
}
400+
401+
void SBLaunchInfo::SetShadowListener(SBListener &listener) {
402+
LLDB_INSTRUMENT_VA(this, listener);
403+
404+
ListenerSP listener_sp = listener.GetSP();
405+
if (listener_sp && listener.IsValid())
406+
listener_sp->SetShadow(true);
407+
else
408+
listener_sp = nullptr;
409+
410+
m_opaque_sp->SetShadowListener(listener_sp);
411+
}

0 commit comments

Comments
 (0)