[Lldb-commits] [lldb] b9d4c94 - [lldb/Plugins] Add Attach capabilities to ScriptedProcess

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 3 19:33:21 PST 2023


Author: Med Ismail Bennani
Date: 2023-03-03T19:33:02-08:00
New Revision: b9d4c94a603d3cc1f44ab7dd1d4f3ae9c80da98b

URL: https://github.com/llvm/llvm-project/commit/b9d4c94a603d3cc1f44ab7dd1d4f3ae9c80da98b
DIFF: https://github.com/llvm/llvm-project/commit/b9d4c94a603d3cc1f44ab7dd1d4f3ae9c80da98b.diff

LOG: [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 <medismail.bennani at gmail.com>

Added: 
    

Modified: 
    lldb/bindings/python/python-swigsafecast.swig
    lldb/bindings/python/python-wrapper.swig
    lldb/examples/python/scripted_process/scripted_process.py
    lldb/include/lldb/API/SBAttachInfo.h
    lldb/include/lldb/API/SBLaunchInfo.h
    lldb/include/lldb/Host/ProcessLaunchInfo.h
    lldb/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/include/lldb/Interpreter/ScriptedMetadata.h
    lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
    lldb/include/lldb/Target/Process.h
    lldb/include/lldb/Target/Target.h
    lldb/include/lldb/Utility/ProcessInfo.h
    lldb/include/lldb/lldb-forward.h
    lldb/source/API/SBAttachInfo.cpp
    lldb/source/API/SBLaunchInfo.cpp
    lldb/source/API/SBTarget.cpp
    lldb/source/Commands/CommandObjectPlatform.cpp
    lldb/source/Commands/CommandObjectProcess.cpp
    lldb/source/Host/common/ProcessLaunchInfo.cpp
    lldb/source/Interpreter/ScriptInterpreter.cpp
    lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
    lldb/source/Plugins/Process/scripted/ScriptedProcess.h
    lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
    lldb/source/Target/Target.cpp
    lldb/source/Utility/ProcessInfo.cpp
    lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
    lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig
index a1e883b3b19d..ae562c26518c 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<lldb::SBCommandReturnObject>
 ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
   return ScopedPythonObject<lldb::SBCommandReturnObject>(

diff  --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 9a08c3000b79..26f79266538a 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 db77e125817e..8f896fc5acce 100644
--- a/lldb/examples/python/scripted_process/scripted_process.py
+++ b/lldb/examples/python/scripted_process/scripted_process.py
@@ -163,6 +163,18 @@ def launch(self):
         """
         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 e296956c0a19..a4dbce29855f 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 @@ class LLDB_API SBAttachInfo {
 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 ace448ed64bc..8c625e1b9068 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 @@ class LLDB_API SBLaunchInfo {
   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 8f8f9333fd1f..b9beea4d11b8 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 @@ class ProcessLaunchInfo : public ProcessInfo {
     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 @@ class ProcessLaunchInfo : public ProcessInfo {
                             // 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 b6b14c80273c..557406b43a53 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 @@ class ScriptInterpreter : public PluginInterface {
 
   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<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo(
       const lldb::SBMemoryRegionInfo &mem_region) const;
 

diff  --git a/lldb/include/lldb/Interpreter/ScriptedMetadata.h b/lldb/include/lldb/Interpreter/ScriptedMetadata.h
index 00ebce323bf8..a4dfe54b762f 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 @@ class ScriptedMetadata {
                    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 @@ class ScriptedMetadata {
     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 0dffa71a873d..1fdac762e51e 100644
--- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
+++ b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
@@ -30,6 +30,10 @@ class ScriptedProcessInterface : virtual public ScriptedInterface {
 
   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 ff2a62a09def..3ffacb52299b 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -193,28 +193,6 @@ class ProcessAttachInfo : public ProcessInstanceInfo {
 
   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 @@ class ProcessAttachInfo : public ProcessInstanceInfo {
       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 5c6e4fe5be9f..7904e78654ef 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1430,6 +1430,8 @@ class Target : public std::enable_shared_from_this<Target>,
     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 cf07418bf1c3..8bddb04b1d47 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 <vector>
 
 namespace lldb_private {
@@ -86,6 +87,16 @@ class ProcessInfo {
   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 @@ class ProcessInfo {
   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 f81852622e4f..e36bdcb61f05 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<lldb_private::RecognizedStackFrame>
 typedef std::shared_ptr<lldb_private::ScriptSummaryFormat>
     ScriptSummaryFormatSP;
 typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
+typedef std::shared_ptr<lldb_private::ScriptedMetadata> ScriptedMetadataSP;
 typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface>
     ScriptedPlatformInterfaceUP;
 typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>

diff  --git a/lldb/source/API/SBAttachInfo.cpp b/lldb/source/API/SBAttachInfo.cpp
index cb66566270b2..ffc61b5860d0 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<ScriptedMetadata>(class_name, nullptr);
+  else
+    metadata_sp = std::make_shared<ScriptedMetadata>(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<ScriptedMetadata>("", dict_sp);
+  else
+    metadata_sp = std::make_shared<ScriptedMetadata>(
+        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 ae191916b49e..5800ac63dddb 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<ScriptedMetadata>(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<ScriptedMetadata>(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 6e5942904db7..ddde1ba6ab8a 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 40e037afdd6d..213631a250bd 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -1188,10 +1188,9 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
 
       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<ScriptedMetadata>(
+            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 @@ class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
 
       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<ScriptedMetadata>(
+            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 ff9992a2aac6..4362b25f9663 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -201,10 +201,9 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
 
     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<ScriptedMetadata>(
+          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 @@ class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
 
     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<ScriptedMetadata>(
+          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 b8827992bc7a..af278cc1a03c 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 90884d20f524..bb3b769a41b5 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<ProcessLaunchInfo>(
+      *reinterpret_cast<ProcessLaunchInfo *>(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 06b35068b384..84e9dea4b7be 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 29676cace33b..004ee7c12742 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -51,6 +51,15 @@ class ScriptedProcess : public Process {
 
   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 @@ class ScriptedProcess : public Process {
   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 3dc2864f8d42..7b7ceff30b65 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<lldb::SBValue> value_sb);
 PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb);
 PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb);
@@ -88,6 +91,8 @@ python::ScopedPythonObject<lldb::SBEvent> 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 3a1db7f35b15..c231828471bf 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<ProcessAttachInfo>(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 6358f9cabffd..076ac37b0420 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
@@ -31,6 +31,8 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
 
   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 789b39abf587..9da46237280f 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 <optional>
@@ -71,6 +70,36 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
   return m_interpreter.GetDataExtractorFromSBData(*sb_data);
 }
 
+template <>
+lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
+    lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) {
+  lldb::SBAttachInfo *sb_attach_info = reinterpret_cast<lldb::SBAttachInfo *>(
+      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<lldb::SBLaunchInfo *>(
+      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<MemoryRegionInfo>
 ScriptedPythonInterface::ExtractValueFromPythonObject<

diff  --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
index 01dc07b49737..aa09be79086a 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
@@ -117,6 +117,14 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
     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 <typename T, typename U>
   void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
     // If U is not a PythonObject, don't touch it!
@@ -198,6 +206,14 @@ template <>
 Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
     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<lldb::DataExtractorSP>(

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 334bb0d54f2e..40d67246c8e8 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3079,6 +3079,17 @@ bool Target::SetSectionUnloaded(const lldb::SectionSP &section_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<ProcessLaunchInfo &>(
+        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<ProcessLaunchInfo &>(
-        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 8e27a17d8337..9ffc409a4695 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 1078db8ad52a..053654c14421 100644
--- a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
+++ b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
@@ -137,8 +137,14 @@ def cleanup():
 
         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 75391e2ce477..1a8ad866e66c 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();
+}


        


More information about the lldb-commits mailing list