From b9d4c94a603d3cc1f44ab7dd1d4f3ae9c80da98b Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Fri, 3 Mar 2023 15:17:59 -0800 Subject: [PATCH] [lldb/Plugins] Add Attach capabilities to ScriptedProcess This patch adds process attach capabilities to the ScriptedProcess plugin. This doesn't really expects a PID or process name, since the process state is already script, however, this allows to create a scripted process without requiring to have an executuble in the target. In order to do so, this patch also turns the scripted process related getters and setters from the `ProcessLaunchInfo` and `ProcessAttachInfo` classes to a `ScriptedMetadata` instance and moves it in the `ProcessInfo` class, so it can be accessed interchangeably. This also adds the necessary SWIG wrappers to convert the internal `Process{Attach,Launch}InfoSP` into a `SB{Attach,Launch}Info` to pass it as argument the scripted process python implementation and convert it back to the internal representation. rdar://104577406 Differential Revision: https://reviews.llvm.org/D143104 Signed-off-by: Med Ismail Bennani --- lldb/bindings/python/python-swigsafecast.swig | 10 ++++++ lldb/bindings/python/python-wrapper.swig | 24 +++++++++++++++ .../python/scripted_process/scripted_process.py | 12 ++++++++ lldb/include/lldb/API/SBAttachInfo.h | 6 ++++ lldb/include/lldb/API/SBLaunchInfo.h | 3 ++ lldb/include/lldb/Host/ProcessLaunchInfo.h | 28 ----------------- lldb/include/lldb/Interpreter/ScriptInterpreter.h | 8 +++++ lldb/include/lldb/Interpreter/ScriptedMetadata.h | 13 +++++--- .../lldb/Interpreter/ScriptedProcessInterface.h | 4 +++ lldb/include/lldb/Target/Process.h | 27 ---------------- lldb/include/lldb/Target/Target.h | 2 ++ lldb/include/lldb/Utility/ProcessInfo.h | 12 ++++++++ lldb/include/lldb/lldb-forward.h | 2 ++ lldb/source/API/SBAttachInfo.cpp | 36 +++++++++++++++++++--- lldb/source/API/SBLaunchInfo.cpp | 27 ++++++++++++---- lldb/source/API/SBTarget.cpp | 3 +- lldb/source/Commands/CommandObjectPlatform.cpp | 14 ++++----- lldb/source/Commands/CommandObjectProcess.cpp | 14 ++++----- lldb/source/Host/common/ProcessLaunchInfo.cpp | 8 ++--- lldb/source/Interpreter/ScriptInterpreter.cpp | 11 +++++++ .../Plugins/Process/scripted/ScriptedProcess.cpp | 28 +++++++++++++++++ .../Plugins/Process/scripted/ScriptedProcess.h | 11 +++++++ .../ScriptInterpreter/Python/SWIGPythonBridge.h | 5 +++ .../Python/ScriptedProcessPythonInterface.cpp | 8 +++++ .../Python/ScriptedProcessPythonInterface.h | 2 ++ .../Python/ScriptedPythonInterface.cpp | 31 ++++++++++++++++++- .../Python/ScriptedPythonInterface.h | 16 ++++++++++ lldb/source/Target/Target.cpp | 28 ++++++++--------- lldb/source/Utility/ProcessInfo.cpp | 6 ++++ .../scripted_process/TestScriptedProcess.py | 8 ++++- .../ScriptInterpreter/Python/PythonTestSuite.cpp | 18 +++++++++++ 31 files changed, 316 insertions(+), 109 deletions(-) diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig index a1e883b..ae562c2 100644 --- a/lldb/bindings/python/python-swigsafecast.swig +++ b/lldb/bindings/python/python-swigsafecast.swig @@ -93,6 +93,16 @@ PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx) { SWIGTYPE_p_lldb__SBSymbolContext); } +PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp) { + return ToSWIGHelper(new lldb::ProcessLaunchInfoSP(std::move(launch_info_sp)), + SWIGTYPE_p_lldb__SBLaunchInfo); + } + + PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp) { + return ToSWIGHelper(new lldb::ProcessAttachInfoSP(std::move(attach_info_sp)), + SWIGTYPE_p_lldb__SBAttachInfo); + } + ScopedPythonObject ToSWIGWrapper(CommandReturnObject &cmd_retobj) { return ScopedPythonObject( diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index 9a08c300..26f7926 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -716,6 +716,30 @@ void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(PyObject * data) { return sb_ptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject * data) { + lldb::SBAttachInfo *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBAttachInfo, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject * data) { + lldb::SBLaunchInfo *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBLaunchInfo, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data) { lldb::SBError *sb_ptr = nullptr; diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/scripted_process/scripted_process.py index db77e12..8f896fc 100644 --- a/lldb/examples/python/scripted_process/scripted_process.py +++ b/lldb/examples/python/scripted_process/scripted_process.py @@ -163,6 +163,18 @@ class ScriptedProcess(metaclass=ABCMeta): """ return lldb.SBError() + def attach(self, attach_info): + """ Simulate the scripted process attach. + + Args: + attach_info (lldb.SBAttachInfo): The information related to the + process we're attaching to. + + Returns: + lldb.SBError: An `lldb.SBError` with error code 0. + """ + return lldb.SBError() + def resume(self): """ Simulate the scripted process resume. diff --git a/lldb/include/lldb/API/SBAttachInfo.h b/lldb/include/lldb/API/SBAttachInfo.h index e296956..a4dbce2 100644 --- a/lldb/include/lldb/API/SBAttachInfo.h +++ b/lldb/include/lldb/API/SBAttachInfo.h @@ -11,6 +11,10 @@ #include "lldb/API/SBDefines.h" +namespace lldb_private { +class ScriptInterpreter; +} + namespace lldb { class SBTarget; @@ -175,6 +179,8 @@ public: protected: friend class SBTarget; + friend class lldb_private::ScriptInterpreter; + lldb_private::ProcessAttachInfo &ref(); ProcessAttachInfoSP m_opaque_sp; diff --git a/lldb/include/lldb/API/SBLaunchInfo.h b/lldb/include/lldb/API/SBLaunchInfo.h index ace448e..8c625e1 100644 --- a/lldb/include/lldb/API/SBLaunchInfo.h +++ b/lldb/include/lldb/API/SBLaunchInfo.h @@ -13,6 +13,7 @@ namespace lldb_private { class SBLaunchInfoImpl; +class ScriptInterpreter; } namespace lldb { @@ -190,6 +191,8 @@ protected: friend class SBPlatform; friend class SBTarget; + friend class lldb_private::ScriptInterpreter; + const lldb_private::ProcessLaunchInfo &ref() const; void set_ref(const lldb_private::ProcessLaunchInfo &info); diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h index 8f8f933..b9beea4 100644 --- a/lldb/include/lldb/Host/ProcessLaunchInfo.h +++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h @@ -20,7 +20,6 @@ #include "lldb/Host/PseudoTerminal.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/ProcessInfo.h" -#include "lldb/Utility/StructuredData.h" namespace lldb_private { @@ -144,28 +143,6 @@ public: return m_flags.Test(lldb::eLaunchFlagDetachOnError); } - bool IsScriptedProcess() const { - return !m_scripted_process_class_name.empty(); - } - - std::string GetScriptedProcessClassName() const { - return m_scripted_process_class_name; - } - - void SetScriptedProcessClassName(std::string name) { - m_scripted_process_class_name = name; - } - - lldb_private::StructuredData::DictionarySP - GetScriptedProcessDictionarySP() const { - return m_scripted_process_dictionary_sp; - } - - void SetScriptedProcessDictionarySP( - lldb_private::StructuredData::DictionarySP dictionary_sp) { - m_scripted_process_dictionary_sp = dictionary_sp; - } - protected: FileSpec m_working_dir; std::string m_plugin_name; @@ -179,11 +156,6 @@ protected: // meaning to the upper levels of lldb. lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; - std::string m_scripted_process_class_name; // The name of the class that will - // manage a scripted process. - StructuredData::DictionarySP - m_scripted_process_dictionary_sp; // A dictionary that holds key/value - // pairs passed to the scripted process. }; } diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index b6b14c8..557406b 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -9,8 +9,10 @@ #ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H #define LLDB_INTERPRETER_SCRIPTINTERPRETER_H +#include "lldb/API/SBAttachInfo.h" #include "lldb/API/SBData.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/PluginInterface.h" @@ -585,6 +587,12 @@ public: Status GetStatusFromSBError(const lldb::SBError &error) const; + lldb::ProcessAttachInfoSP + GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const; + + lldb::ProcessLaunchInfoSP + GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const; + std::optional GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const; diff --git a/lldb/include/lldb/Interpreter/ScriptedMetadata.h b/lldb/include/lldb/Interpreter/ScriptedMetadata.h index 00ebce3..a4dfe54 100644 --- a/lldb/include/lldb/Interpreter/ScriptedMetadata.h +++ b/lldb/include/lldb/Interpreter/ScriptedMetadata.h @@ -12,7 +12,7 @@ #include "OptionGroupPythonClassWithDict.h" #include "lldb/Host/Host.h" -#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/StructuredData.h" namespace lldb_private { @@ -22,9 +22,12 @@ public: StructuredData::DictionarySP dict_sp) : m_class_name(class_name.data()), m_args_sp(dict_sp) {} - ScriptedMetadata(const ProcessLaunchInfo &launch_info) { - m_class_name = launch_info.GetScriptedProcessClassName(); - m_args_sp = launch_info.GetScriptedProcessDictionarySP(); + ScriptedMetadata(const ProcessInfo &process_info) { + lldb::ScriptedMetadataSP metadata_sp = process_info.GetScriptedMetadata(); + if (metadata_sp) { + m_class_name = metadata_sp->GetClassName(); + m_args_sp = metadata_sp->GetArgsSP(); + } } ScriptedMetadata(const OptionGroupPythonClassWithDict &option_group) { @@ -33,6 +36,8 @@ public: m_args_sp = opt_group.GetStructuredData(); } + explicit operator bool() const { return !m_class_name.empty(); } + llvm::StringRef GetClassName() const { return m_class_name; } StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; } diff --git a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h index 0dffa71..1fdac76 100644 --- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -30,6 +30,10 @@ public: virtual StructuredData::DictionarySP GetCapabilities() { return {}; } + virtual Status Attach(const ProcessAttachInfo &attach_info) { + return Status("ScriptedProcess did not attach"); + } + virtual Status Launch() { return Status("ScriptedProcess did not launch"); } virtual Status Resume() { return Status("ScriptedProcess did not resume"); } diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index ff2a62a..3ffacb5 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -193,28 +193,6 @@ public: lldb::ListenerSP GetListenerForProcess(Debugger &debugger); - bool IsScriptedProcess() const { - return !m_scripted_process_class_name.empty(); - } - - std::string GetScriptedProcessClassName() const { - return m_scripted_process_class_name; - } - - void SetScriptedProcessClassName(std::string name) { - m_scripted_process_class_name = name; - } - - lldb_private::StructuredData::DictionarySP - GetScriptedProcessDictionarySP() const { - return m_scripted_process_dictionary_sp; - } - - void SetScriptedProcessDictionarySP( - lldb_private::StructuredData::DictionarySP dictionary_sp) { - m_scripted_process_dictionary_sp = dictionary_sp; - } - protected: lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; @@ -232,11 +210,6 @@ protected: false; // Use an async attach where we start the attach and return // immediately (used by GUI programs with --waitfor so they can // call SBProcess::Stop() to cancel attach) - std::string m_scripted_process_class_name; // The name of the class that will - // manage a scripted process. - StructuredData::DictionarySP - m_scripted_process_dictionary_sp; // A dictionary that holds key/value - // pairs passed to the scripted process. }; // This class tracks the Modification state of the process. Things that can diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 5c6e4fe..7904e78 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -1430,6 +1430,8 @@ public: return *m_frame_recognizer_manager_up; } + void SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info); + /// Add a signal for the target. This will get copied over to the process /// if the signal exists on that target. Only the values with Yes and No are /// set, Calculate values will be ignored. diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h index cf07418..8bddb04 100644 --- a/lldb/include/lldb/Utility/ProcessInfo.h +++ b/lldb/include/lldb/Utility/ProcessInfo.h @@ -14,6 +14,7 @@ #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/StructuredData.h" #include namespace lldb_private { @@ -86,6 +87,16 @@ public: Environment &GetEnvironment() { return m_environment; } const Environment &GetEnvironment() const { return m_environment; } + bool IsScriptedProcess() const; + + lldb::ScriptedMetadataSP GetScriptedMetadata() const { + return m_scripted_metadata_sp; + } + + void SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp) { + m_scripted_metadata_sp = metadata_sp; + } + protected: FileSpec m_executable; std::string m_arg0; // argv[0] if supported. If empty, then use m_executable. @@ -97,6 +108,7 @@ protected: uint32_t m_gid = UINT32_MAX; ArchSpec m_arch; lldb::pid_t m_pid = LLDB_INVALID_PROCESS_ID; + lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr; }; // ProcessInstanceInfo diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index f818526..e36bdcb 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -181,6 +181,7 @@ class RichManglingContext; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; +class ScriptedMetadata; class ScriptedPlatformInterface; class ScriptedProcessInterface; class ScriptedThreadInterface; @@ -380,6 +381,7 @@ typedef std::shared_ptr typedef std::shared_ptr ScriptSummaryFormatSP; typedef std::shared_ptr ScriptInterpreterSP; +typedef std::shared_ptr ScriptedMetadataSP; typedef std::unique_ptr ScriptedPlatformInterfaceUP; typedef std::unique_ptr diff --git a/lldb/source/API/SBAttachInfo.cpp b/lldb/source/API/SBAttachInfo.cpp index cb66566..ffc61b5 100644 --- a/lldb/source/API/SBAttachInfo.cpp +++ b/lldb/source/API/SBAttachInfo.cpp @@ -11,6 +11,7 @@ #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBStructuredData.h" +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Target/Process.h" #include "lldb/Utility/Instrumentation.h" @@ -256,25 +257,41 @@ void SBAttachInfo::SetListener(SBListener &listener) { const char *SBAttachInfo::GetScriptedProcessClassName() const { LLDB_INSTRUMENT_VA(this); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + + if (!metadata_sp || !*metadata_sp) + return nullptr; + // Constify this string so that it is saved in the string pool. Otherwise it // would be freed when this function goes out of scope. - ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str()); + ConstString class_name(metadata_sp->GetClassName().data()); return class_name.AsCString(); } void SBAttachInfo::SetScriptedProcessClassName(const char *class_name) { LLDB_INSTRUMENT_VA(this, class_name); - m_opaque_sp->SetScriptedProcessClassName(class_name); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + + if (!metadata_sp) + metadata_sp = std::make_shared(class_name, nullptr); + else + metadata_sp = std::make_shared(class_name, + metadata_sp->GetArgsSP()); + + m_opaque_sp->SetScriptedMetadata(metadata_sp); } lldb::SBStructuredData SBAttachInfo::GetScriptedProcessDictionary() const { LLDB_INSTRUMENT_VA(this); - lldb_private::StructuredData::DictionarySP dict_sp = - m_opaque_sp->GetScriptedProcessDictionarySP(); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); SBStructuredData data; + if (!metadata_sp) + return data; + + lldb_private::StructuredData::DictionarySP dict_sp = metadata_sp->GetArgsSP(); data.m_impl_up->SetObjectSP(dict_sp); return data; @@ -282,6 +299,7 @@ lldb::SBStructuredData SBAttachInfo::GetScriptedProcessDictionary() const { void SBAttachInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) { LLDB_INSTRUMENT_VA(this, dict); + if (!dict.IsValid() || !dict.m_impl_up) return; @@ -295,5 +313,13 @@ void SBAttachInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) { if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) return; - m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + + if (!metadata_sp) + metadata_sp = std::make_shared("", dict_sp); + else + metadata_sp = std::make_shared( + metadata_sp->GetClassName(), dict_sp); + + m_opaque_sp->SetScriptedMetadata(metadata_sp); } diff --git a/lldb/source/API/SBLaunchInfo.cpp b/lldb/source/API/SBLaunchInfo.cpp index ae19191..5800ac6 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/Interpreter/ScriptedMetadata.h" using namespace lldb; using namespace lldb_private; @@ -331,25 +332,36 @@ bool SBLaunchInfo::GetDetachOnError() const { const char *SBLaunchInfo::GetScriptedProcessClassName() const { LLDB_INSTRUMENT_VA(this); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + + if (!metadata_sp || !*metadata_sp) + return nullptr; + // Constify this string so that it is saved in the string pool. Otherwise it // would be freed when this function goes out of scope. - ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str()); + ConstString class_name(metadata_sp->GetClassName().data()); return class_name.AsCString(); } void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) { LLDB_INSTRUMENT_VA(this, class_name); - - m_opaque_sp->SetScriptedProcessClassName(class_name); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + StructuredData::DictionarySP dict_sp = + metadata_sp ? metadata_sp->GetArgsSP() : nullptr; + metadata_sp = std::make_shared(class_name, dict_sp); + m_opaque_sp->SetScriptedMetadata(metadata_sp); } lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const { LLDB_INSTRUMENT_VA(this); - lldb_private::StructuredData::DictionarySP dict_sp = - m_opaque_sp->GetScriptedProcessDictionarySP(); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); SBStructuredData data; + if (!metadata_sp) + return data; + + lldb_private::StructuredData::DictionarySP dict_sp = metadata_sp->GetArgsSP(); data.m_impl_up->SetObjectSP(dict_sp); return data; @@ -370,5 +382,8 @@ void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) { if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) return; - m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp); + ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata(); + llvm::StringRef class_name = metadata_sp ? metadata_sp->GetClassName() : ""; + metadata_sp = std::make_shared(class_name, dict_sp); + m_opaque_sp->SetScriptedMetadata(metadata_sp); } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 6e59429..ddde1ba 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -434,7 +434,8 @@ lldb::SBProcess SBTarget::Attach(SBAttachInfo &sb_attach_info, SBError &error) { if (target_sp) { ProcessAttachInfo &attach_info = sb_attach_info.ref(); - if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid()) { + if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid() && + !attach_info.IsScriptedProcess()) { PlatformSP platform_sp = target_sp->GetPlatform(); // See if we can pre-verify if a process exists or not if (platform_sp && platform_sp->IsConnected()) { diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 40e037a..213631a 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -1188,10 +1188,9 @@ protected: if (!m_class_options.GetName().empty()) { m_options.launch_info.SetProcessPluginName("ScriptedProcess"); - m_options.launch_info.SetScriptedProcessClassName( - m_class_options.GetName()); - m_options.launch_info.SetScriptedProcessDictionarySP( - m_class_options.GetStructuredData()); + ScriptedMetadataSP metadata_sp = std::make_shared( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.launch_info.SetScriptedMetadata(metadata_sp); target->SetProcessLaunchInfo(m_options.launch_info); } @@ -1608,10 +1607,9 @@ public: if (!m_class_options.GetName().empty()) { m_options.attach_info.SetProcessPluginName("ScriptedProcess"); - m_options.attach_info.SetScriptedProcessClassName( - m_class_options.GetName()); - m_options.attach_info.SetScriptedProcessDictionarySP( - m_class_options.GetStructuredData()); + ScriptedMetadataSP metadata_sp = std::make_shared( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.attach_info.SetScriptedMetadata(metadata_sp); } Status err; diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index ff9992a..4362b25 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -201,10 +201,9 @@ protected: if (!m_class_options.GetName().empty()) { m_options.launch_info.SetProcessPluginName("ScriptedProcess"); - m_options.launch_info.SetScriptedProcessClassName( - m_class_options.GetName()); - m_options.launch_info.SetScriptedProcessDictionarySP( - m_class_options.GetStructuredData()); + ScriptedMetadataSP metadata_sp = std::make_shared( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.launch_info.SetScriptedMetadata(metadata_sp); target->SetProcessLaunchInfo(m_options.launch_info); } @@ -356,10 +355,9 @@ protected: if (!m_class_options.GetName().empty()) { m_options.attach_info.SetProcessPluginName("ScriptedProcess"); - m_options.attach_info.SetScriptedProcessClassName( - m_class_options.GetName()); - m_options.attach_info.SetScriptedProcessDictionarySP( - m_class_options.GetStructuredData()); + ScriptedMetadataSP metadata_sp = std::make_shared( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.attach_info.SetScriptedMetadata(metadata_sp); } // Record the old executable module, we want to issue a warning if the diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp index b882799..af278cc 100644 --- a/lldb/source/Host/common/ProcessLaunchInfo.cpp +++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp @@ -32,8 +32,7 @@ using namespace lldb_private; ProcessLaunchInfo::ProcessLaunchInfo() : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0), m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr), - m_listener_sp(), m_hijack_listener_sp(), m_scripted_process_class_name(), - m_scripted_process_dictionary_sp() {} + m_listener_sp(), m_hijack_listener_sp() {} ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, @@ -41,8 +40,7 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &working_directory, uint32_t launch_flags) : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags), - m_file_actions(), m_pty(new PseudoTerminal), - m_scripted_process_class_name(), m_scripted_process_dictionary_sp() { + m_file_actions(), m_pty(new PseudoTerminal) { if (stdin_file_spec) { FileAction file_action; const bool read = true; @@ -171,8 +169,6 @@ void ProcessLaunchInfo::Clear() { m_resume_count = 0; m_listener_sp.reset(); m_hijack_listener_sp.reset(); - m_scripted_process_class_name.clear(); - m_scripted_process_dictionary_sp.reset(); } void ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, int signal, diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 90884d2..bb3b769 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -80,6 +80,17 @@ ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const { return data.m_opaque_sp; } +lldb::ProcessAttachInfoSP ScriptInterpreter::GetOpaqueTypeFromSBAttachInfo( + const lldb::SBAttachInfo &attach_info) const { + return attach_info.m_opaque_sp; +} + +lldb::ProcessLaunchInfoSP ScriptInterpreter::GetOpaqueTypeFromSBLaunchInfo( + const lldb::SBLaunchInfo &launch_info) const { + return std::make_shared( + *reinterpret_cast(launch_info.m_opaque_sp.get())); +} + Status ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const { if (error.m_opaque_up) diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index 06b3506..84e9dea 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -195,6 +195,34 @@ Status ScriptedProcess::DoResume() { return error; } +Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) { + Status error = GetInterface().Attach(attach_info); + SetPrivateState(eStateRunning); + SetPrivateState(eStateStopped); + if (error.Fail()) + return error; + // NOTE: We need to set the PID before finishing to attach otherwise we will + // hit an assert when calling the attach completion handler. + DidLaunch(); + + return {}; +} + +Status +ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) { + return DoAttach(attach_info); +} + +Status ScriptedProcess::DoAttachToProcessWithName( + const char *process_name, const ProcessAttachInfo &attach_info) { + return DoAttach(attach_info); +} + +void ScriptedProcess::DidAttach(ArchSpec &process_arch) { + process_arch = GetArchitecture(); +} + Status ScriptedProcess::DoStop() { Log *log = GetLog(LLDBLog::Process); diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h index 29676ca..004ee7c 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -51,6 +51,15 @@ public: Status DoResume() override; + Status DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) override; + + Status + DoAttachToProcessWithName(const char *process_name, + const ProcessAttachInfo &attach_info) override; + + void DidAttach(ArchSpec &process_arch) override; + Status DoDestroy() override; void RefreshStateAfterStop() override; @@ -90,6 +99,8 @@ protected: Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; + Status DoAttach(const ProcessAttachInfo &attach_info); + private: friend class ScriptedThread; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 3dc2864..7b7ceff 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -77,6 +77,9 @@ PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp); PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options); PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx); +PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp); +PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp); + PythonObject ToSWIGWrapper(std::unique_ptr value_sb); PythonObject ToSWIGWrapper(std::unique_ptr stream_sb); PythonObject ToSWIGWrapper(std::unique_ptr data_sb); @@ -88,6 +91,8 @@ python::ScopedPythonObject ToSWIGWrapper(Event *event); } // namespace python void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index 3a1db7f..c231828 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" +#include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" @@ -67,6 +68,13 @@ StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { return dict; } +Status +ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { + lldb::ProcessAttachInfoSP attach_info_sp = + std::make_shared(attach_info); + return GetStatusFromMethod("attach", attach_info_sp); +} + Status ScriptedProcessPythonInterface::Launch() { return GetStatusFromMethod("launch"); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h index 6358f9c..076ac37 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -31,6 +31,8 @@ public: StructuredData::DictionarySP GetCapabilities() override; + Status Attach(const ProcessAttachInfo &attach_info) override; + Status Launch() override; Status Resume() override; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp index 789b39a..9da4623 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -15,7 +15,6 @@ // LLDB Python header must be included first #include "lldb-python.h" -#include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" #include @@ -72,6 +71,36 @@ ScriptedPythonInterface::ExtractValueFromPythonObject( } template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBAttachInfo *sb_attach_info = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get())); + + if (!sb_attach_info) { + error.SetErrorString( + "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info); +} + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get())); + + if (!sb_launch_info) { + error.SetErrorString( + "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info); +} + +template <> std::optional ScriptedPythonInterface::ExtractValueFromPythonObject< std::optional>(python::PythonObject &p, Status &error) { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h index 01dc07b..aa09be7 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -117,6 +117,14 @@ protected: return python::ToSWIGWrapper(arg); } + python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { + return python::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { + return python::ToSWIGWrapper(arg); + } + template void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { // If U is not a PythonObject, don't touch it! @@ -199,6 +207,14 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject( python::PythonObject &p, Status &error); template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); + +template <> lldb::DataExtractorSP ScriptedPythonInterface::ExtractValueFromPythonObject( python::PythonObject &p, Status &error); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 334bb0d..40d6724 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -3079,6 +3079,17 @@ bool Target::SetSectionUnloaded(const lldb::SectionSP §ion_sp, void Target::ClearAllLoadedSections() { m_section_load_history.Clear(); } +void Target::SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info) { + if (process_info.IsScriptedProcess()) { + // Only copy scripted process launch options. + ProcessLaunchInfo &default_launch_info = const_cast( + GetGlobalProperties().GetProcessLaunchInfo()); + default_launch_info.SetProcessPluginName("ScriptedProcess"); + default_launch_info.SetScriptedMetadata(process_info.GetScriptedMetadata()); + SetProcessLaunchInfo(default_launch_info); + } +} + Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { m_stats.SetLaunchOrAttachTime(); Status error; @@ -3108,19 +3119,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { launch_info.GetFlags().Set(eLaunchFlagDebug); - if (launch_info.IsScriptedProcess()) { - // Only copy scripted process launch options. - ProcessLaunchInfo &default_launch_info = const_cast( - GetGlobalProperties().GetProcessLaunchInfo()); - - default_launch_info.SetProcessPluginName("ScriptedProcess"); - default_launch_info.SetScriptedProcessClassName( - launch_info.GetScriptedProcessClassName()); - default_launch_info.SetScriptedProcessDictionarySP( - launch_info.GetScriptedProcessDictionarySP()); - - SetProcessLaunchInfo(launch_info); - } + SaveScriptedLaunchInfo(launch_info); // Get the value of synchronous execution here. If you wait till after you // have started to run, then you could have hit a breakpoint, whose command @@ -3333,11 +3332,12 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) { Status error; if (state != eStateConnected && platform_sp != nullptr && - platform_sp->CanDebugProcess()) { + platform_sp->CanDebugProcess() && !attach_info.IsScriptedProcess()) { SetPlatform(platform_sp); process_sp = platform_sp->Attach(attach_info, GetDebugger(), this, error); } else { if (state != eStateConnected) { + SaveScriptedLaunchInfo(attach_info); const char *plugin_name = attach_info.GetProcessPluginName(); process_sp = CreateProcess(attach_info.GetListenerForProcess(GetDebugger()), diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp index 8e27a17..9ffc409 100644 --- a/lldb/source/Utility/ProcessInfo.cpp +++ b/lldb/source/Utility/ProcessInfo.cpp @@ -8,6 +8,7 @@ #include "lldb/Utility/ProcessInfo.h" +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" @@ -36,6 +37,7 @@ void ProcessInfo::Clear() { m_gid = UINT32_MAX; m_arch.Clear(); m_pid = LLDB_INVALID_PROCESS_ID; + m_scripted_metadata_sp.reset(); } const char *ProcessInfo::GetName() const { @@ -109,6 +111,10 @@ void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) { } } +bool ProcessInfo::IsScriptedProcess() const { + return m_scripted_metadata_sp && *m_scripted_metadata_sp; +} + void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const { if (m_pid != LLDB_INVALID_PROCESS_ID) s.Printf(" pid = %" PRIu64 "\n", m_pid); diff --git a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py index 1078db8..053654c 100644 --- a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py @@ -137,8 +137,14 @@ class ScriptedProcesTestCase(TestBase): target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target_1, VALID_TARGET) + + # We still need to specify a PID when attaching even for scripted processes + attach_info = lldb.SBAttachInfo(42) + attach_info.SetProcessPluginName("ScriptedProcess") + attach_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") + error = lldb.SBError() - process_1 = target_1.Launch(launch_info, error) + process_1 = target_1.Attach(attach_info, error) self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID) self.assertEqual(process_1.GetProcessID(), 42) self.assertEqual(process_1.GetNumThreads(), 1) diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp index 75391e2..1a8ad86 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -139,6 +139,14 @@ void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(PyObject *data) { return nullptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data) { + return nullptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data) { + return nullptr; +} + void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject *data) { return nullptr; } @@ -268,3 +276,13 @@ bool lldb_private::LLDBSwigPythonStopHookCallHandleStop( python::PythonObject lldb_private::python::ToSWIGWrapper(const Status &status) { return python::PythonObject(); } + +python::PythonObject +lldb_private::python::ToSWIGWrapper(lldb::ProcessAttachInfoSP) { + return python::PythonObject(); +} + +python::PythonObject +lldb_private::python::ToSWIGWrapper(lldb::ProcessLaunchInfoSP) { + return python::PythonObject(); +} -- 2.7.4