[Lldb-commits] [lldb] 6382fcb - [lldb/Utility] Add opt-in shadow mode to event listeners
Med Ismail Bennani via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 25 15:04:22 PDT 2023
Author: Med Ismail Bennani
Date: 2023-04-25T15:02:34-07:00
New Revision: 6382fcb16def5ae4a47082466fd8dc93e8fdf988
URL: https://github.com/llvm/llvm-project/commit/6382fcb16def5ae4a47082466fd8dc93e8fdf988
DIFF: https://github.com/llvm/llvm-project/commit/6382fcb16def5ae4a47082466fd8dc93e8fdf988.diff
LOG: [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 <medismail.bennani at gmail.com>
Added:
Modified:
lldb/include/lldb/API/SBAttachInfo.h
lldb/include/lldb/API/SBLaunchInfo.h
lldb/include/lldb/Target/Process.h
lldb/include/lldb/Utility/Broadcaster.h
lldb/include/lldb/Utility/Listener.h
lldb/include/lldb/Utility/ProcessInfo.h
lldb/source/API/SBAttachInfo.cpp
lldb/source/API/SBLaunchInfo.cpp
lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
lldb/source/Target/Target.cpp
lldb/source/Utility/Broadcaster.cpp
lldb/source/Utility/Listener.cpp
lldb/source/Utility/ProcessInfo.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/API/SBAttachInfo.h b/lldb/include/lldb/API/SBAttachInfo.h
index a4dbce29855f2..ea1145e625856 100644
--- a/lldb/include/lldb/API/SBAttachInfo.h
+++ b/lldb/include/lldb/API/SBAttachInfo.h
@@ -168,6 +168,25 @@ class LLDB_API SBAttachInfo {
/// allows a
diff erent listener to be used to listen for process events.
void SetListener(SBListener &listener);
+ /// Get the shadow listener that receive public process events,
+ /// additionally to the default process event listener.
+ ///
+ /// If no listener has been set via a call to
+ /// SBLaunchInfo::SetShadowListener(), then an invalid SBListener will
+ /// be returned (SBListener::IsValid() will return false). If a listener
+ /// has been set, then the valid listener object will be returned.
+ SBListener GetShadowListener();
+
+ /// Set the shadow listener that will receive public process events,
+ /// additionally to the default process event listener.
+ ///
+ /// By default a process have no shadow event listener.
+ /// Calling this function allows public process events to be broadcasted to an
+ /// additional listener on top of the default process event listener.
+ /// If the `listener` argument is invalid (SBListener::IsValid() will
+ /// return false), this will clear the shadow listener.
+ void SetShadowListener(SBListener &listener);
+
const char *GetScriptedProcessClassName() const;
void SetScriptedProcessClassName(const char *class_name);
diff --git a/lldb/include/lldb/API/SBLaunchInfo.h b/lldb/include/lldb/API/SBLaunchInfo.h
index 8c625e1b9068e..06e72efc30f9f 100644
--- a/lldb/include/lldb/API/SBLaunchInfo.h
+++ b/lldb/include/lldb/API/SBLaunchInfo.h
@@ -92,6 +92,25 @@ class LLDB_API SBLaunchInfo {
/// allows a
diff erent listener to be used to listen for process events.
void SetListener(SBListener &listener);
+ /// Get the shadow listener that receive public process events,
+ /// additionally to the default process event listener.
+ ///
+ /// If no listener has been set via a call to
+ /// SBLaunchInfo::SetShadowListener(), then an invalid SBListener will
+ /// be returned (SBListener::IsValid() will return false). If a listener
+ /// has been set, then the valid listener object will be returned.
+ SBListener GetShadowListener();
+
+ /// Set the shadow listener that will receive public process events,
+ /// additionally to the default process event listener.
+ ///
+ /// By default a process have no shadow event listener.
+ /// Calling this function allows public process events to be broadcasted to an
+ /// additional listener on top of the default process event listener.
+ /// If the `listener` argument is invalid (SBListener::IsValid() will
+ /// return false), this will clear the shadow listener.
+ void SetShadowListener(SBListener &listener);
+
uint32_t GetNumArguments();
const char *GetArgumentAtIndex(uint32_t idx);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 68581e47184cb..207b4939d0232 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -380,6 +380,10 @@ class Process : public std::enable_shared_from_this<Process>,
return GetStaticBroadcasterClass();
}
+ void SetShadowListener(lldb::ListenerSP listener_sp) override {
+ Broadcaster::SetShadowListener(listener_sp);
+ }
+
/// A notification structure that can be used by clients to listen
/// for changes in a process's lifetime.
///
diff --git a/lldb/include/lldb/Utility/Broadcaster.h b/lldb/include/lldb/Utility/Broadcaster.h
index 9c025a7c7dd88..85e2468a111f5 100644
--- a/lldb/include/lldb/Utility/Broadcaster.h
+++ b/lldb/include/lldb/Utility/Broadcaster.h
@@ -406,6 +406,10 @@ class Broadcaster {
lldb::BroadcasterManagerSP GetManager();
+ virtual void SetShadowListener(lldb::ListenerSP listener_sp) {
+ m_broadcaster_sp->m_shadow_listener = listener_sp;
+ }
+
protected:
/// BroadcasterImpl contains the actual Broadcaster implementation. The
/// Broadcaster makes a BroadcasterImpl which lives as long as it does. The
@@ -513,6 +517,10 @@ class Broadcaster {
/// for now this is just for private hijacking.
std::vector<uint32_t> m_hijacking_masks;
+ /// A optional listener that all private events get also broadcasted to,
+ /// on top the hijacked / default listeners.
+ lldb::ListenerSP m_shadow_listener = nullptr;
+
private:
BroadcasterImpl(const BroadcasterImpl &) = delete;
const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete;
diff --git a/lldb/include/lldb/Utility/Listener.h b/lldb/include/lldb/Utility/Listener.h
index d70e778c94803..8d50fe77d6a29 100644
--- a/lldb/include/lldb/Utility/Listener.h
+++ b/lldb/include/lldb/Utility/Listener.h
@@ -95,6 +95,8 @@ class Listener : public std::enable_shared_from_this<Listener> {
size_t HandleBroadcastEvent(lldb::EventSP &event_sp);
+ void SetShadow(bool is_shadow) { m_is_shadow = is_shadow; }
+
private:
// Classes that inherit from Listener can see and modify these
struct BroadcasterInfo {
@@ -134,6 +136,7 @@ class Listener : public std::enable_shared_from_this<Listener> {
std::mutex m_events_mutex; // Protects m_broadcasters and m_events
std::condition_variable m_events_condition;
broadcaster_manager_collection m_broadcaster_managers;
+ bool m_is_shadow = false;
void BroadcasterWillDestruct(Broadcaster *);
diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h
index a48acdddca3ab..f56b30ab82ec6 100644
--- a/lldb/include/lldb/Utility/ProcessInfo.h
+++ b/lldb/include/lldb/Utility/ProcessInfo.h
@@ -110,6 +110,12 @@ class ProcessInfo {
m_hijack_listener_sp = listener_sp;
}
+ lldb::ListenerSP GetShadowListener() const { return m_shadow_listener_sp; }
+
+ void SetShadowListener(const lldb::ListenerSP &listener_sp) {
+ m_shadow_listener_sp = listener_sp;
+ }
+
protected:
FileSpec m_executable;
std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
@@ -124,6 +130,7 @@ class ProcessInfo {
lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
lldb::ListenerSP m_listener_sp = nullptr;
lldb::ListenerSP m_hijack_listener_sp = nullptr;
+ lldb::ListenerSP m_shadow_listener_sp = nullptr;
};
// ProcessInstanceInfo
diff --git a/lldb/source/API/SBAttachInfo.cpp b/lldb/source/API/SBAttachInfo.cpp
index 0d2dacbf9c78c..1cd1146f5d317 100644
--- a/lldb/source/API/SBAttachInfo.cpp
+++ b/lldb/source/API/SBAttachInfo.cpp
@@ -254,6 +254,27 @@ void SBAttachInfo::SetListener(SBListener &listener) {
m_opaque_sp->SetListener(listener.GetSP());
}
+SBListener SBAttachInfo::GetShadowListener() {
+ LLDB_INSTRUMENT_VA(this);
+
+ lldb::ListenerSP shadow_sp = m_opaque_sp->GetShadowListener();
+ if (!shadow_sp)
+ return SBListener();
+ return SBListener(shadow_sp);
+}
+
+void SBAttachInfo::SetShadowListener(SBListener &listener) {
+ LLDB_INSTRUMENT_VA(this, listener);
+
+ ListenerSP listener_sp = listener.GetSP();
+ if (listener_sp && listener.IsValid())
+ listener_sp->SetShadow(true);
+ else
+ listener_sp = nullptr;
+
+ m_opaque_sp->SetShadowListener(listener_sp);
+}
+
const char *SBAttachInfo::GetScriptedProcessClassName() const {
LLDB_INSTRUMENT_VA(this);
diff --git a/lldb/source/API/SBLaunchInfo.cpp b/lldb/source/API/SBLaunchInfo.cpp
index 21ae84b4e3cc4..b3ed1b3ac2e60 100644
--- a/lldb/source/API/SBLaunchInfo.cpp
+++ b/lldb/source/API/SBLaunchInfo.cpp
@@ -17,6 +17,7 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/Utility/ScriptedMetadata.h"
using namespace lldb;
@@ -387,3 +388,24 @@ void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
m_opaque_sp->SetScriptedMetadata(metadata_sp);
}
+
+SBListener SBLaunchInfo::GetShadowListener() {
+ LLDB_INSTRUMENT_VA(this);
+
+ lldb::ListenerSP shadow_sp = m_opaque_sp->GetShadowListener();
+ if (!shadow_sp)
+ return SBListener();
+ return SBListener(shadow_sp);
+}
+
+void SBLaunchInfo::SetShadowListener(SBListener &listener) {
+ LLDB_INSTRUMENT_VA(this, listener);
+
+ ListenerSP listener_sp = listener.GetSP();
+ if (listener_sp && listener.IsValid())
+ listener_sp->SetShadow(true);
+ else
+ listener_sp = nullptr;
+
+ m_opaque_sp->SetShadowListener(listener_sp);
+}
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 222dbfa719647..1e91f2ccd1982 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -401,6 +401,7 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info,
attach_info.SetHijackListener(listener_sp);
}
process_sp->HijackProcessEvents(listener_sp);
+ process_sp->SetShadowListener(attach_info.GetShadowListener());
error = process_sp->Attach(attach_info);
}
}
@@ -458,6 +459,7 @@ lldb::ProcessSP PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info,
LLDB_LOG(log, "successfully created process");
process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+ process_sp->SetShadowListener(launch_info.GetShadowListener());
// Log file actions.
if (log) {
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 446776519dd24..a6106dccdb7f8 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -423,6 +423,7 @@ PlatformRemoteGDBServer::DebugProcess(ProcessLaunchInfo &launch_info,
if (process_sp) {
process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+ process_sp->SetShadowListener(launch_info.GetShadowListener());
error = process_sp->ConnectRemote(connect_url.c_str());
// Retry the connect remote one time...
@@ -515,6 +516,7 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach(
ListenerSP listener_sp = attach_info.GetHijackListener();
if (listener_sp)
process_sp->HijackProcessEvents(listener_sp);
+ process_sp->SetShadowListener(attach_info.GetShadowListener());
error = process_sp->Attach(attach_info);
}
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 4f3c644e82889..84e399fc52d29 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3194,6 +3194,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
// Since we didn't have a platform launch the process, launch it here.
if (m_process_sp) {
m_process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+ m_process_sp->SetShadowListener(launch_info.GetShadowListener());
error = m_process_sp->Launch(launch_info);
}
}
diff --git a/lldb/source/Utility/Broadcaster.cpp b/lldb/source/Utility/Broadcaster.cpp
index 31530f8a6443d..4e6710e1108b3 100644
--- a/lldb/source/Utility/Broadcaster.cpp
+++ b/lldb/source/Utility/Broadcaster.cpp
@@ -228,6 +228,8 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp,
&m_broadcaster, event_type))
return;
hijacking_listener_sp->AddEvent(event_sp);
+ if (m_shadow_listener)
+ m_shadow_listener->AddEvent(event_sp);
} else {
for (auto &pair : GetListeners()) {
if (!(pair.second & event_type))
@@ -237,6 +239,8 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp,
continue;
pair.first->AddEvent(event_sp);
+ if (m_shadow_listener)
+ m_shadow_listener->AddEvent(event_sp);
}
}
}
diff --git a/lldb/source/Utility/Listener.cpp b/lldb/source/Utility/Listener.cpp
index 8bb55f93bbf8c..2286827c51385 100644
--- a/lldb/source/Utility/Listener.cpp
+++ b/lldb/source/Utility/Listener.cpp
@@ -35,7 +35,7 @@ class BroadcasterManagerWPMatcher {
Listener::Listener(const char *name)
: m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
- m_events_mutex() {
+ m_events_mutex(), m_is_shadow() {
Log *log = GetLog(LLDBLog::Object);
if (log != nullptr)
LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
@@ -302,7 +302,8 @@ bool Listener::FindNextEventInternal(
// to return it so it should be okay to get the next event off the queue
// here - and it might be useful to do that in the "DoOnRemoval".
lock.unlock();
- event_sp->DoOnRemoval();
+ if (!m_is_shadow)
+ event_sp->DoOnRemoval();
}
return true;
}
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 29a7064438bcc..6b2a7114dfb4c 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -23,13 +23,13 @@ using namespace lldb_private;
ProcessInfo::ProcessInfo()
: m_executable(), m_arguments(), m_environment(), m_arch(), m_listener_sp(),
- m_hijack_listener_sp(), m_passthrough_listener_sp() {}
+ m_hijack_listener_sp(), m_shadow_listener_sp() {}
ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
lldb::pid_t pid)
: m_executable(name), m_arguments(), m_environment(), m_arch(arch),
m_pid(pid), m_listener_sp(), m_hijack_listener_sp(),
- m_passthrough_listener_sp() {}
+ m_shadow_listener_sp() {}
void ProcessInfo::Clear() {
m_executable.Clear();
More information about the lldb-commits
mailing list