[Lldb-commits] [lldb] [lldb] Unifying Scripted Affordance Interfaces (wip) (PR #68052)

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Sat Oct 21 02:53:38 PDT 2023


https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/68052

>From 849ee46635684452975a0c1635c5185ecbd6132a Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Thu, 31 Aug 2023 13:13:57 +0100
Subject: [PATCH 1/9] [lldb] Move ScriptInterpreter Interfaces to subdirectory
 (NFC)

As we're consolidating and  streamlining the various scripting
affordances of lldb, we keep creating new interface files.

This patch groups all the current interface files into a separate sub
directory called `Interfaces` both in the core `Interpreter` directory
and the `ScriptInterpreter` plugin directory.

Differential Revision: https://reviews.llvm.org/D158833

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 .../{ => Interfaces}/ScriptedInterface.h      |  6 +--
 .../ScriptedPlatformInterface.h               |  8 +--
 .../ScriptedProcessInterface.h                | 38 ++------------
 .../Interfaces/ScriptedThreadInterface.h      | 52 +++++++++++++++++++
 .../lldb/Interpreter/ScriptInterpreter.h      |  9 +++-
 .../ScriptInterpreter/Python/CMakeLists.txt   |  7 ++-
 .../Python/Interfaces/CMakeLists.txt          | 38 ++++++++++++++
 .../ScriptedPlatformPythonInterface.cpp       |  6 +--
 .../ScriptedPlatformPythonInterface.h         |  8 +--
 .../ScriptedProcessPythonInterface.cpp        |  8 +--
 .../ScriptedProcessPythonInterface.h          |  8 +--
 .../ScriptedPythonInterface.cpp               |  4 +-
 .../ScriptedPythonInterface.h                 | 15 +++---
 .../ScriptedThreadPythonInterface.cpp         |  6 +--
 .../ScriptedThreadPythonInterface.h           |  8 +--
 .../Python/ScriptInterpreterPython.cpp        | 10 +++-
 .../Python/ScriptInterpreterPythonImpl.h      |  1 +
 17 files changed, 151 insertions(+), 81 deletions(-)
 rename lldb/include/lldb/Interpreter/{ => Interfaces}/ScriptedInterface.h (93%)
 rename lldb/include/lldb/Interpreter/{ => Interfaces}/ScriptedPlatformInterface.h (85%)
 rename lldb/include/lldb/Interpreter/{ => Interfaces}/ScriptedProcessInterface.h (68%)
 create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
 create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedPlatformPythonInterface.cpp (97%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedPlatformPythonInterface.h (80%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedProcessPythonInterface.cpp (97%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedProcessPythonInterface.h (86%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedPythonInterface.cpp (98%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedPythonInterface.h (95%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedThreadPythonInterface.cpp (97%)
 rename lldb/source/Plugins/ScriptInterpreter/Python/{ => Interfaces}/ScriptedThreadPythonInterface.h (81%)

diff --git a/lldb/include/lldb/Interpreter/ScriptedInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
similarity index 93%
rename from lldb/include/lldb/Interpreter/ScriptedInterface.h
rename to lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
index ab6142593264374..948f763e95ecea4 100644
--- a/lldb/include/lldb/Interpreter/ScriptedInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_INTERPRETER_SCRIPTEDINTERFACE_H
-#define LLDB_INTERPRETER_SCRIPTEDINTERFACE_H
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
 
 #include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Target/ExecutionContext.h"
@@ -74,4 +74,4 @@ class ScriptedInterface {
   StructuredData::GenericSP m_object_instance_sp;
 };
 } // namespace lldb_private
-#endif // LLDB_INTERPRETER_SCRIPTEDINTERFACE_H
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
similarity index 85%
rename from lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h
rename to lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
index 2db1fef0be721e6..c687cabfe0c1278 100644
--- a/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H
-#define LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDPLATFORMINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDPLATFORMINTERFACE_H
 
 #include "lldb/Core/StructuredDataImpl.h"
-#include "lldb/Interpreter/ScriptedInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedInterface.h"
 
 #include "lldb/lldb-private.h"
 
@@ -46,4 +46,4 @@ class ScriptedPlatformInterface : virtual public ScriptedInterface {
 };
 } // namespace lldb_private
 
-#endif // LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDPLATFORMINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
similarity index 68%
rename from lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
rename to lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
index 210b1081cddcd79..68756c4d9ac858d 100644
--- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H
-#define LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDPROCESSINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDPROCESSINTERFACE_H
 
+#include "ScriptedInterface.h"
 #include "lldb/Core/StructuredDataImpl.h"
-#include "lldb/Interpreter/ScriptedInterface.h"
 #include "lldb/Target/MemoryRegionInfo.h"
 
 #include "lldb/lldb-private.h"
@@ -80,36 +80,6 @@ class ScriptedProcessInterface : virtual public ScriptedInterface {
     return {};
   }
 };
-
-class ScriptedThreadInterface : virtual public ScriptedInterface {
-public:
-  StructuredData::GenericSP
-  CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
-                     StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override {
-    return {};
-  }
-
-  virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; }
-
-  virtual std::optional<std::string> GetName() { return std::nullopt; }
-
-  virtual lldb::StateType GetState() { return lldb::eStateInvalid; }
-
-  virtual std::optional<std::string> GetQueue() { return std::nullopt; }
-
-  virtual StructuredData::DictionarySP GetStopReason() { return {}; }
-
-  virtual StructuredData::ArraySP GetStackFrames() { return {}; }
-
-  virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; }
-
-  virtual std::optional<std::string> GetRegisterContext() {
-    return std::nullopt;
-  }
-
-  virtual StructuredData::ArraySP GetExtendedInfo() { return {}; }
-};
 } // namespace lldb_private
 
-#endif // LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDPROCESSINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
new file mode 100644
index 000000000000000..781df51a213229a
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
@@ -0,0 +1,52 @@
+//===-- ScriptedThreadInterface.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADINTERFACE_H
+
+#include "ScriptedInterface.h"
+#include "lldb/Core/StructuredDataImpl.h"
+
+#include "lldb/lldb-private.h"
+
+#include <optional>
+#include <string>
+
+namespace lldb_private {
+class ScriptedThreadInterface : virtual public ScriptedInterface {
+public:
+  StructuredData::GenericSP
+  CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
+                     StructuredData::DictionarySP args_sp,
+                     StructuredData::Generic *script_obj = nullptr) override {
+    return {};
+  }
+
+  virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; }
+
+  virtual std::optional<std::string> GetName() { return std::nullopt; }
+
+  virtual lldb::StateType GetState() { return lldb::eStateInvalid; }
+
+  virtual std::optional<std::string> GetQueue() { return std::nullopt; }
+
+  virtual StructuredData::DictionarySP GetStopReason() { return {}; }
+
+  virtual StructuredData::ArraySP GetStackFrames() { return {}; }
+
+  virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; }
+
+  virtual std::optional<std::string> GetRegisterContext() {
+    return std::nullopt;
+  }
+
+  virtual StructuredData::ArraySP GetExtendedInfo() { return {}; }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 7ee251e2087502e..eacd10d5279be6f 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -21,9 +21,10 @@
 #include "lldb/Core/ThreadedCommunication.h"
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/StreamFile.h"
+#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
 #include "lldb/Interpreter/ScriptObject.h"
-#include "lldb/Interpreter/ScriptedPlatformInterface.h"
-#include "lldb/Interpreter/ScriptedProcessInterface.h"
 #include "lldb/Utility/Broadcaster.h"
 #include "lldb/Utility/Status.h"
 #include "lldb/Utility/StructuredData.h"
@@ -588,6 +589,10 @@ class ScriptInterpreter : public PluginInterface {
     return std::make_unique<ScriptedProcessInterface>();
   }
 
+  virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() {
+    return std::make_shared<ScriptedThreadInterface>();
+  }
+
   ScriptedPlatformInterface &GetScriptedPlatformInterface() {
     return *m_scripted_platform_interface_up;
   }
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
index 72361166964241a..7523d65abf0f802 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
@@ -19,14 +19,12 @@ if (LLDB_ENABLE_LIBEDIT)
   list(APPEND LLDB_LIBEDIT_LIBS LibEdit::LibEdit)
 endif()
 
+add_subdirectory(Interfaces)
+
 add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
   PythonDataObjects.cpp
   PythonReadline.cpp
   ScriptInterpreterPython.cpp
-  ScriptedPythonInterface.cpp
-  ScriptedProcessPythonInterface.cpp
-  ScriptedThreadPythonInterface.cpp
-  ScriptedPlatformPythonInterface.cpp
 
   LINK_LIBS
     lldbBreakpoint
@@ -35,6 +33,7 @@ add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
     lldbHost
     lldbInterpreter
     lldbTarget
+    lldbPluginScriptInterpreterPythonInterfaces
     ${Python3_LIBRARIES}
     ${LLDB_LIBEDIT_LIBS}
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
new file mode 100644
index 000000000000000..73aeb32ead855e8
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
@@ -0,0 +1,38 @@
+if (APPLE AND LLVM_ENABLE_LOCAL_SUBMODULE_VISIBILITY)
+  # Work around an issue with the Python headers, which have a modular include
+  # inside an extern "C" block.
+  remove_module_flags()
+endif()
+
+if(NOT LLDB_PYTHON_RELATIVE_PATH)
+  message(FATAL_ERROR "LLDB_PYTHON_RELATIVE_PATH is not set.")
+endif()
+add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${LLDB_PYTHON_RELATIVE_PATH}")
+
+if(NOT LLDB_PYTHON_EXE_RELATIVE_PATH)
+  message(FATAL_ERROR "LLDB_PYTHON_EXE_RELATIVE_PATH is not set.")
+endif()
+add_definitions(-DLLDB_PYTHON_EXE_RELATIVE_PATH="${LLDB_PYTHON_EXE_RELATIVE_PATH}")
+
+
+if (LLDB_ENABLE_LIBEDIT)
+  list(APPEND LLDB_LIBEDIT_LIBS LibEdit::LibEdit)
+endif()
+
+add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
+  ScriptedPythonInterface.cpp
+  ScriptedProcessPythonInterface.cpp
+  ScriptedThreadPythonInterface.cpp
+  ScriptedPlatformPythonInterface.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbInterpreter
+    lldbTarget
+    ${Python3_LIBRARIES}
+    ${LLDB_LIBEDIT_LIBS}
+
+  LINK_COMPONENTS
+    Support
+  )
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
similarity index 97%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
index a0c55874c70a4a0..9bed33516915d08 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
@@ -14,10 +14,10 @@
 #if LLDB_ENABLE_PYTHON
 
 // LLDB Python header must be included first
-#include "lldb-python.h"
+#include "../lldb-python.h"
 
-#include "SWIGPythonBridge.h"
-#include "ScriptInterpreterPythonImpl.h"
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
 #include "ScriptedPlatformPythonInterface.h"
 
 using namespace lldb;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
similarity index 80%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
index 1e3ad9962325a3f..02deecd15ede062 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H
-#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H
 
 #include "lldb/Host/Config.h"
 
 #if LLDB_ENABLE_PYTHON
 
 #include "ScriptedPythonInterface.h"
-#include "lldb/Interpreter/ScriptedPlatformInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
 
 namespace lldb_private {
 class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface,
@@ -41,4 +41,4 @@ class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface,
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
-#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
similarity index 97%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
index 019924fa19718f0..63a4db1ff5973e7 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
@@ -9,7 +9,7 @@
 #include "lldb/Host/Config.h"
 #if LLDB_ENABLE_PYTHON
 // LLDB Python header must be included first
-#include "lldb-python.h"
+#include "../lldb-python.h"
 #endif
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/Log.h"
@@ -18,8 +18,8 @@
 
 #if LLDB_ENABLE_PYTHON
 
-#include "SWIGPythonBridge.h"
-#include "ScriptInterpreterPythonImpl.h"
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
 #include "ScriptedProcessPythonInterface.h"
 #include "ScriptedThreadPythonInterface.h"
 #include <optional>
@@ -199,7 +199,7 @@ ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
 
 lldb::ScriptedThreadInterfaceSP
 ScriptedProcessPythonInterface::CreateScriptedThreadInterface() {
-  return std::make_shared<ScriptedThreadPythonInterface>(m_interpreter);
+  return m_interpreter.CreateScriptedThreadInterface();
 }
 
 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
similarity index 86%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
index ff03eab07648a84..11330f5591b74e6 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
-#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H
 
 #include "lldb/Host/Config.h"
 
 #if LLDB_ENABLE_PYTHON
 
 #include "ScriptedPythonInterface.h"
-#include "lldb/Interpreter/ScriptedProcessInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
 #include <optional>
 
 namespace lldb_private {
@@ -68,4 +68,4 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
-#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
similarity index 98%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 1e36a81fde54e8b..6f22503b279ca62 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -13,9 +13,9 @@
 #if LLDB_ENABLE_PYTHON
 
 // LLDB Python header must be included first
-#include "lldb-python.h"
+#include "../lldb-python.h"
 
-#include "ScriptInterpreterPythonImpl.h"
+#include "../ScriptInterpreterPythonImpl.h"
 #include "ScriptedPythonInterface.h"
 #include <optional>
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
similarity index 95%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 4d0645d18acad4a..9163b8f6aede7d1 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
-#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
 
 #if LLDB_ENABLE_PYTHON
 
@@ -18,12 +18,12 @@
 #include <utility>
 
 #include "lldb/Host/Config.h"
-#include "lldb/Interpreter/ScriptedInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedInterface.h"
 #include "lldb/Utility/DataBufferHeap.h"
 
-#include "PythonDataObjects.h"
-#include "SWIGPythonBridge.h"
-#include "ScriptInterpreterPythonImpl.h"
+#include "../PythonDataObjects.h"
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
 
 namespace lldb_private {
 class ScriptInterpreterPythonImpl;
@@ -146,7 +146,6 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
     original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error);
   }
 
-
   void ReverseTransform(bool &original_arg,
                         python::PythonObject transformed_arg, Status &error) {
     python::PythonBoolean boolean_arg = python::PythonBoolean(
@@ -254,4 +253,4 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
-#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
similarity index 97%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
index 5603a1541314a56..6addcd46e045efc 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
@@ -13,10 +13,10 @@
 #if LLDB_ENABLE_PYTHON
 
 // LLDB Python header must be included first
-#include "lldb-python.h"
+#include "../lldb-python.h"
 
-#include "SWIGPythonBridge.h"
-#include "ScriptInterpreterPythonImpl.h"
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
 #include "ScriptedThreadPythonInterface.h"
 #include <optional>
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
similarity index 81%
rename from lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h
rename to lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
index eac4941f88145dd..b63760fd5b5713d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H
-#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H
 
 #include "lldb/Host/Config.h"
 
 #if LLDB_ENABLE_PYTHON
 
 #include "ScriptedPythonInterface.h"
-#include "lldb/Interpreter/ScriptedProcessInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
 #include <optional>
 
 namespace lldb_private {
@@ -49,4 +49,4 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface,
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
-#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 0d6ff6660acd3db..66e6ac796c9340b 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -14,12 +14,13 @@
 // LLDB Python header must be included first
 #include "lldb-python.h"
 
+#include "Interfaces/ScriptedPlatformPythonInterface.h"
+#include "Interfaces/ScriptedProcessPythonInterface.h"
+#include "Interfaces/ScriptedThreadPythonInterface.h"
 #include "PythonDataObjects.h"
 #include "PythonReadline.h"
 #include "SWIGPythonBridge.h"
 #include "ScriptInterpreterPythonImpl.h"
-#include "ScriptedPlatformPythonInterface.h"
-#include "ScriptedProcessPythonInterface.h"
 
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBFrame.h"
@@ -1515,6 +1516,11 @@ ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {
   return std::make_unique<ScriptedProcessPythonInterface>(*this);
 }
 
+ScriptedThreadInterfaceSP
+ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
+  return std::make_shared<ScriptedThreadPythonInterface>(*this);
+}
+
 StructuredData::ObjectSP
 ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
     ScriptObject obj) {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 01db6c5203007a1..00dc1d1baa309f6 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -140,6 +140,7 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
 
   StructuredData::DictionarySP
   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
+  lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
 
   StructuredData::ArraySP
   OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;

>From f55770bce5b9f7a1f5fac620d772f9e2d56a24b2 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Thu, 31 Aug 2023 22:37:35 +0100
Subject: [PATCH 2/9] [lldb] Move template python files to separate directory

This patch moves the template files for the various scripting
affordances to a separate directory.

This is a preparatory work for upcoming improvements and consolidations
to other scripting affordances.

Differential Revision: https://reviews.llvm.org/D159310

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/CMakeLists.txt                         | 6 +++---
 .../{scripted_process => }/crashlog_scripted_process.py     | 0
 .../{scripted_process => templates}/scripted_platform.py    | 0
 .../{scripted_process => templates}/scripted_process.py     | 0
 4 files changed, 3 insertions(+), 3 deletions(-)
 rename lldb/examples/python/{scripted_process => }/crashlog_scripted_process.py (100%)
 rename lldb/examples/python/{scripted_process => templates}/scripted_platform.py (100%)
 rename lldb/examples/python/{scripted_process => templates}/scripted_process.py (100%)

diff --git a/lldb/bindings/python/CMakeLists.txt b/lldb/bindings/python/CMakeLists.txt
index 2cc3ad1bb98b73e..c4806bda27049c6 100644
--- a/lldb/bindings/python/CMakeLists.txt
+++ b/lldb/bindings/python/CMakeLists.txt
@@ -103,15 +103,15 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar
     ${lldb_python_target_dir}
     "plugins"
     FILES
-    "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py"
-    "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_platform.py")
+    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_process.py"
+    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py")
 
   if(APPLE)
     create_python_package(
       ${swig_target}
       ${lldb_python_target_dir} "macosx"
       FILES "${LLDB_SOURCE_DIR}/examples/python/crashlog.py"
-            "${LLDB_SOURCE_DIR}/examples/python/scripted_process/crashlog_scripted_process.py"
+            "${LLDB_SOURCE_DIR}/examples/python/crashlog_scripted_process.py"
             "${LLDB_SOURCE_DIR}/examples/darwin/heap_find/heap.py")
 
     create_python_package(
diff --git a/lldb/examples/python/scripted_process/crashlog_scripted_process.py b/lldb/examples/python/crashlog_scripted_process.py
similarity index 100%
rename from lldb/examples/python/scripted_process/crashlog_scripted_process.py
rename to lldb/examples/python/crashlog_scripted_process.py
diff --git a/lldb/examples/python/scripted_process/scripted_platform.py b/lldb/examples/python/templates/scripted_platform.py
similarity index 100%
rename from lldb/examples/python/scripted_process/scripted_platform.py
rename to lldb/examples/python/templates/scripted_platform.py
diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/templates/scripted_process.py
similarity index 100%
rename from lldb/examples/python/scripted_process/scripted_process.py
rename to lldb/examples/python/templates/scripted_process.py

>From e6dafc2851377fb148d7310fa56cd3cd75094108 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Thu, 31 Aug 2023 23:05:18 +0100
Subject: [PATCH 3/9] [lldb] Introduce OperatingSystem{,Python}Interface and
 make us it

This patch aims to consolidate the OperatingSystem scripting affordance
by introducing a stable interface that conforms to the
Scripted{,Python}Interface.

This unify the way we call into python methods from lldb while
also improving its capabilities by allowing us to pass lldb_private
objects are arguments.

Differential Revision: https://reviews.llvm.org/D159314

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/python-wrapper.swig      |  17 +-
 lldb/bindings/python/python.swig              |   1 +
 .../Interfaces/OperatingSystemInterface.h     |  33 ++++
 .../lldb/Interpreter/ScriptInterpreter.h      |  11 +-
 lldb/include/lldb/lldb-forward.h              |   3 +
 .../Python/OperatingSystemPython.cpp          | 150 +++++++----------
 .../Python/OperatingSystemPython.h            |   7 +-
 .../Python/Interfaces/CMakeLists.txt          |   1 +
 .../OperatingSystemPythonInterface.cpp        |  77 +++++++++
 .../OperatingSystemPythonInterface.h          |  44 +++++
 .../Python/ScriptInterpreterPython.cpp        | 159 +-----------------
 .../Python/ScriptInterpreterPythonImpl.h      |  17 +-
 12 files changed, 251 insertions(+), 269 deletions(-)
 create mode 100644 lldb/include/lldb/Interpreter/Interfaces/OperatingSystemInterface.h
 create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
 create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h

diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index cb54901e66d03c6..758fdf6c80c0029 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -263,11 +263,20 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedObjec
   }
 
   PythonObject result = {};
-  if (arg_info.get().max_positional_args == 2) {
+  switch (arg_info.get().max_positional_args) {
+    case 1:
+      // FIXME: Since this is used by different scripting affordances, they can have different number
+      // of argument but also different types of arguments (i.e SBExecutionContect vs SBProcess)
+      // We need to have a more reliable way to forward positional arguments.
+      result = pfunc(SWIGBridge::ToSWIGWrapper(exe_ctx_sp->GetProcessSP()));
+      break;
+    case 2:
       result = pfunc(SWIGBridge::ToSWIGWrapper(exe_ctx_sp), SWIGBridge::ToSWIGWrapper(args_impl));
-  } else {
-    error_string.assign("wrong number of arguments in __init__, should be 2 "
-                        "(not including self)");
+      break;
+    default:
+      error_string.assign("wrong number of arguments in __init__, should be 2 "
+                          "(not including self)");
+      break;
   }
   return result;
 }
diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig
index 278c0eed2bab27f..a8ead02250d9cd0 100644
--- a/lldb/bindings/python/python.swig
+++ b/lldb/bindings/python/python.swig
@@ -116,6 +116,7 @@ def lldb_iter(obj, getsize, getelem):
 %{
 #include "../source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
 #include "../source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h"
+#include "../include/lldb/Target/ExecutionContext.h"
 #include "../bindings/python/python-swigsafecast.swig"
 using namespace lldb_private;
 using namespace lldb_private::python;
diff --git a/lldb/include/lldb/Interpreter/Interfaces/OperatingSystemInterface.h b/lldb/include/lldb/Interpreter/Interfaces/OperatingSystemInterface.h
new file mode 100644
index 000000000000000..3c46f99f3b356fe
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/OperatingSystemInterface.h
@@ -0,0 +1,33 @@
+//===-- OperatingSystemInterface.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H
+
+#include "ScriptedThreadInterface.h"
+#include "lldb/Core/StructuredDataImpl.h"
+
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+class OperatingSystemInterface : virtual public ScriptedThreadInterface {
+public:
+  virtual StructuredData::DictionarySP CreateThread(lldb::tid_t tid,
+                                                    lldb::addr_t context) {
+    return {};
+  }
+
+  virtual StructuredData::ArraySP GetThreadInfo() { return {}; }
+
+  virtual std::optional<std::string> GetRegisterContextForTID(lldb::tid_t tid) {
+    return std::nullopt;
+  }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index eacd10d5279be6f..57a1962441e9510 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -21,6 +21,7 @@
 #include "lldb/Core/ThreadedCommunication.h"
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/StreamFile.h"
+#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
 #include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
 #include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
 #include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
@@ -252,12 +253,6 @@ class ScriptInterpreter : public PluginInterface {
     return lldb::ValueObjectListSP();
   }
 
-  virtual StructuredData::GenericSP
-  OSPlugin_CreatePluginObject(const char *class_name,
-                              lldb::ProcessSP process_sp) {
-    return StructuredData::GenericSP();
-  }
-
   virtual StructuredData::DictionarySP
   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) {
     return StructuredData::DictionarySP();
@@ -593,6 +588,10 @@ class ScriptInterpreter : public PluginInterface {
     return std::make_shared<ScriptedThreadInterface>();
   }
 
+  virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() {
+    return std::make_shared<OperatingSystemInterface>();
+  }
+
   ScriptedPlatformInterface &GetScriptedPlatformInterface() {
     return *m_scripted_platform_interface_up;
   }
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 3cd71c8a4ba3c0a..aa099d4abc3b09f 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -130,6 +130,7 @@ class ObjectContainer;
 class ObjectFile;
 class ObjectFileJITDelegate;
 class OperatingSystem;
+class OperatingSystemInterface;
 class OptionGroup;
 class OptionGroupOptions;
 class OptionGroupPlatform;
@@ -360,6 +361,8 @@ typedef std::shared_ptr<lldb_private::ObjectFileJITDelegate>
 typedef std::weak_ptr<lldb_private::ObjectFileJITDelegate>
     ObjectFileJITDelegateWP;
 typedef std::unique_ptr<lldb_private::OperatingSystem> OperatingSystemUP;
+typedef std::shared_ptr<lldb_private::OperatingSystemInterface>
+    OperatingSystemInterfaceSP;
 typedef std::shared_ptr<lldb_private::OptionValue> OptionValueSP;
 typedef std::weak_ptr<lldb_private::OptionValue> OptionValueWP;
 typedef std::shared_ptr<lldb_private::OptionValueProperties>
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 9560ae108f3e354..9a5dd515489231c 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -74,47 +74,69 @@ llvm::StringRef OperatingSystemPython::GetPluginDescriptionStatic() {
 OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
                                              const FileSpec &python_module_path)
     : OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_up(),
-      m_interpreter(nullptr), m_python_object_sp() {
+      m_interpreter(nullptr), m_script_object_sp() {
   if (!process)
     return;
   TargetSP target_sp = process->CalculateTarget();
   if (!target_sp)
     return;
   m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
-  if (m_interpreter) {
-
-    std::string os_plugin_class_name(
-        python_module_path.GetFilename().AsCString(""));
-    if (!os_plugin_class_name.empty()) {
-      LoadScriptOptions options;
-      char python_module_path_cstr[PATH_MAX];
-      python_module_path.GetPath(python_module_path_cstr,
-                                 sizeof(python_module_path_cstr));
-      Status error;
-      if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
-                                             error)) {
-        // Strip the ".py" extension if there is one
-        size_t py_extension_pos = os_plugin_class_name.rfind(".py");
-        if (py_extension_pos != std::string::npos)
-          os_plugin_class_name.erase(py_extension_pos);
-        // Add ".OperatingSystemPlugIn" to the module name to get a string like
-        // "modulename.OperatingSystemPlugIn"
-        os_plugin_class_name += ".OperatingSystemPlugIn";
-        StructuredData::ObjectSP object_sp =
-            m_interpreter->OSPlugin_CreatePluginObject(
-                os_plugin_class_name.c_str(), process->CalculateProcess());
-        if (object_sp && object_sp->IsValid())
-          m_python_object_sp = object_sp;
-      }
-    }
-  }
+  if (!m_interpreter)
+    return;
+
+  std::string os_plugin_class_name(
+      python_module_path.GetFilename().AsCString(""));
+  if (os_plugin_class_name.empty())
+    return;
+
+  LoadScriptOptions options;
+  char python_module_path_cstr[PATH_MAX];
+  python_module_path.GetPath(python_module_path_cstr,
+                             sizeof(python_module_path_cstr));
+  Status error;
+  if (!m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
+                                          error))
+    return;
+
+  // Strip the ".py" extension if there is one
+  size_t py_extension_pos = os_plugin_class_name.rfind(".py");
+  if (py_extension_pos != std::string::npos)
+    os_plugin_class_name.erase(py_extension_pos);
+  // Add ".OperatingSystemPlugIn" to the module name to get a string like
+  // "modulename.OperatingSystemPlugIn"
+  os_plugin_class_name += ".OperatingSystemPlugIn";
+
+  auto operating_system_interface =
+      m_interpreter->CreateOperatingSystemInterface();
+  if (!operating_system_interface)
+    //    return llvm::createStringError(
+    //        llvm::inconvertibleErrorCode(),
+    //        "Failed to create scripted thread interface.");
+    return;
+
+  ExecutionContext exe_ctx(process);
+  StructuredData::GenericSP owned_script_object_sp =
+      operating_system_interface->CreatePluginObject(os_plugin_class_name,
+                                                     exe_ctx, nullptr);
+
+  if (!owned_script_object_sp)
+    //    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+    //                                   "Failed to create script object.");
+    return;
+  if (!owned_script_object_sp->IsValid())
+    //    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+    //                                   "Created script object is invalid.");
+    return;
+
+  m_script_object_sp = owned_script_object_sp;
+  m_operating_system_interface_sp = operating_system_interface;
 }
 
 OperatingSystemPython::~OperatingSystemPython() = default;
 
 DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
   if (m_register_info_up == nullptr) {
-    if (!m_interpreter || !m_python_object_sp)
+    if (!m_interpreter || !m_operating_system_interface_sp)
       return nullptr;
     Log *log = GetLog(LLDBLog::OS);
 
@@ -124,7 +146,7 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
               m_process->GetID());
 
     StructuredData::DictionarySP dictionary =
-        m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp);
+        m_operating_system_interface_sp->GetRegisterInfo();
     if (!dictionary)
       return nullptr;
 
@@ -140,27 +162,11 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
 bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
                                              ThreadList &core_thread_list,
                                              ThreadList &new_thread_list) {
-  if (!m_interpreter || !m_python_object_sp)
+  if (!m_interpreter || !m_operating_system_interface_sp)
     return false;
 
   Log *log = GetLog(LLDBLog::OS);
 
-  // First thing we have to do is to try to get the API lock, and the
-  // interpreter lock. We're going to change the thread content of the process,
-  // and we're going to use python, which requires the API lock to do it. We
-  // need the interpreter lock to make sure thread_info_dict stays alive.
-  //
-  // If someone already has the API lock, that is ok, we just want to avoid
-  // external code from making new API calls while this call is happening.
-  //
-  // This is a recursive lock so we can grant it to any Python code called on
-  // the stack below us.
-  Target &target = m_process->GetTarget();
-  std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
-                                                  std::defer_lock);
-  (void)api_lock.try_lock(); // See above.
-  auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
-
   LLDB_LOGF(log,
             "OperatingSystemPython::UpdateThreadList() fetching thread "
             "data from python for pid %" PRIu64,
@@ -170,7 +176,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
   // the lldb_private::Process subclass, no memory threads will be in this
   // list.
   StructuredData::ArraySP threads_list =
-      m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);
+      m_operating_system_interface_sp->GetThreadInfo();
 
   const uint32_t num_cores = core_thread_list.GetSize(false);
 
@@ -281,28 +287,12 @@ RegisterContextSP
 OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
                                                       addr_t reg_data_addr) {
   RegisterContextSP reg_ctx_sp;
-  if (!m_interpreter || !m_python_object_sp || !thread)
+  if (!m_interpreter || !m_script_object_sp || !thread)
     return reg_ctx_sp;
 
   if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
     return reg_ctx_sp;
 
-  // First thing we have to do is to try to get the API lock, and the
-  // interpreter lock. We're going to change the thread content of the process,
-  // and we're going to use python, which requires the API lock to do it. We
-  // need the interpreter lock to make sure thread_info_dict stays alive.
-  //
-  // If someone already has the API lock, that is ok, we just want to avoid
-  // external code from making new API calls while this call is happening.
-  //
-  // This is a recursive lock so we can grant it to any Python code called on
-  // the stack below us.
-  Target &target = m_process->GetTarget();
-  std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
-                                                  std::defer_lock);
-  (void)api_lock.try_lock(); // See above.
-  auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
-
   Log *log = GetLog(LLDBLog::Thread);
 
   if (reg_data_addr != LLDB_INVALID_ADDRESS) {
@@ -324,11 +314,11 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
               ") fetching register data from python",
               thread->GetID(), thread->GetProtocolID());
 
-    StructuredData::StringSP reg_context_data =
-        m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp,
-                                                    thread->GetID());
+    std::optional<std::string> reg_context_data =
+        m_operating_system_interface_sp->GetRegisterContextForTID(
+            thread->GetID());
     if (reg_context_data) {
-      std::string value = std::string(reg_context_data->GetValue());
+      std::string value = *reg_context_data;
       DataBufferSP data_sp(new DataBufferHeap(value.c_str(), value.length()));
       if (data_sp->GetByteSize()) {
         RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory(
@@ -347,6 +337,7 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
               "OperatingSystemPython::CreateRegisterContextForThread (tid "
               "= 0x%" PRIx64 ") forcing a dummy register context",
               thread->GetID());
+    Target &target = m_process->GetTarget();
     reg_ctx_sp = std::make_shared<RegisterContextDummy>(
         *thread, 0, target.GetArchitecture().GetAddressByteSize());
   }
@@ -372,26 +363,11 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
             ", context = 0x%" PRIx64 ") fetching register data from python",
             tid, context);
 
-  if (m_interpreter && m_python_object_sp) {
-    // First thing we have to do is to try to get the API lock, and the
-    // interpreter lock. We're going to change the thread content of the
-    // process, and we're going to use python, which requires the API lock to
-    // do it. We need the interpreter lock to make sure thread_info_dict stays
-    // alive.
-    //
-    // If someone already has the API lock, that is ok, we just want to avoid
-    // external code from making new API calls while this call is happening.
-    //
-    // This is a recursive lock so we can grant it to any Python code called on
-    // the stack below us.
-    Target &target = m_process->GetTarget();
-    std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
-                                                    std::defer_lock);
-    (void)api_lock.try_lock(); // See above.
-    auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
+  if (m_interpreter && m_script_object_sp) {
 
     StructuredData::DictionarySP thread_info_dict =
-        m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
+        m_operating_system_interface_sp->CreateThread(tid, context);
+
     std::vector<bool> core_used_map;
     if (thread_info_dict) {
       ThreadList core_threads(m_process);
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index 7800cf03af8e888..90973acde3ebfd0 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -62,7 +62,7 @@ class OperatingSystemPython : public lldb_private::OperatingSystem {
 
 protected:
   bool IsValid() const {
-    return m_python_object_sp && m_python_object_sp->IsValid();
+    return m_script_object_sp && m_script_object_sp->IsValid();
   }
 
   lldb::ThreadSP CreateThreadFromThreadInfo(
@@ -75,8 +75,9 @@ class OperatingSystemPython : public lldb_private::OperatingSystem {
 
   lldb::ValueObjectSP m_thread_list_valobj_sp;
   std::unique_ptr<lldb_private::DynamicRegisterInfo> m_register_info_up;
-  lldb_private::ScriptInterpreter *m_interpreter;
-  lldb_private::StructuredData::ObjectSP m_python_object_sp;
+  lldb_private::ScriptInterpreter *m_interpreter = nullptr;
+  lldb::OperatingSystemInterfaceSP m_operating_system_interface_sp = nullptr;
+  lldb_private::StructuredData::GenericSP m_script_object_sp = nullptr;
 };
 
 #endif // LLDB_ENABLE_PYTHON
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
index 73aeb32ead855e8..b22abc49c92a9a9 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
@@ -20,6 +20,7 @@ if (LLDB_ENABLE_LIBEDIT)
 endif()
 
 add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
+  OperatingSystemPythonInterface.cpp
   ScriptedPythonInterface.cpp
   ScriptedProcessPythonInterface.cpp
   ScriptedThreadPythonInterface.cpp
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
new file mode 100644
index 000000000000000..45804d5d019d79d
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
@@ -0,0 +1,77 @@
+//===-- ScriptedThreadPythonInterface.cpp ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Config.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "../lldb-python.h"
+
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
+#include "OperatingSystemPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+using Locker = ScriptInterpreterPythonImpl::Locker;
+
+OperatingSystemPythonInterface::OperatingSystemPythonInterface(
+    ScriptInterpreterPythonImpl &interpreter)
+    : OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {}
+
+StructuredData::GenericSP OperatingSystemPythonInterface::CreatePluginObject(
+    llvm::StringRef class_name, ExecutionContext &exe_ctx,
+    StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
+  return ScriptedThreadPythonInterface::CreatePluginObject(class_name, exe_ctx,
+                                                           args_sp, script_obj);
+}
+
+StructuredData::DictionarySP
+OperatingSystemPythonInterface::CreateThread(lldb::tid_t tid,
+                                             lldb::addr_t context) {
+  Status error;
+  StructuredData::DictionarySP dict = Dispatch<StructuredData::DictionarySP>(
+      "create_thread", error, tid, context);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
+    return {};
+
+  return dict;
+}
+
+StructuredData::ArraySP OperatingSystemPythonInterface::GetThreadInfo() {
+  Status error;
+  StructuredData::ArraySP arr =
+      Dispatch<StructuredData::ArraySP>("get_thread_info", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
+    return {};
+
+  return arr;
+}
+
+StructuredData::DictionarySP OperatingSystemPythonInterface::GetRegisterInfo() {
+  return ScriptedThreadPythonInterface::GetRegisterInfo();
+}
+
+std::optional<std::string>
+OperatingSystemPythonInterface::GetRegisterContextForTID(lldb::tid_t tid) {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("get_register_data", error, tid);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return {};
+
+  return obj->GetAsString()->GetValue().str();
+}
+
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
new file mode 100644
index 000000000000000..a69557ad7c43469
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
@@ -0,0 +1,44 @@
+//===-- OperatingSystemPythonInterface.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "ScriptedThreadPythonInterface.h"
+#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
+#include <optional>
+
+namespace lldb_private {
+class OperatingSystemPythonInterface
+    : virtual public OperatingSystemInterface,
+      virtual public ScriptedThreadPythonInterface {
+public:
+  OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter);
+
+  StructuredData::GenericSP
+  CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
+                     StructuredData::DictionarySP args_sp,
+                     StructuredData::Generic *script_obj = nullptr) override;
+
+  StructuredData::DictionarySP CreateThread(lldb::tid_t tid,
+                                            lldb::addr_t context) override;
+
+  StructuredData::ArraySP GetThreadInfo() override;
+
+  StructuredData::DictionarySP GetRegisterInfo() override;
+
+  std::optional<std::string> GetRegisterContextForTID(lldb::tid_t tid) override;
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 66e6ac796c9340b..a57c8e4984ad8a8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -14,6 +14,7 @@
 // LLDB Python header must be included first
 #include "lldb-python.h"
 
+#include "Interfaces/OperatingSystemPythonInterface.h"
 #include "Interfaces/ScriptedPlatformPythonInterface.h"
 #include "Interfaces/ScriptedProcessPythonInterface.h"
 #include "Interfaces/ScriptedThreadPythonInterface.h"
@@ -1521,6 +1522,11 @@ ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
   return std::make_shared<ScriptedThreadPythonInterface>(*this);
 }
 
+OperatingSystemInterfaceSP
+ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {
+  return std::make_shared<OperatingSystemPythonInterface>(*this);
+}
+
 StructuredData::ObjectSP
 ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
     ScriptObject obj) {
@@ -1532,159 +1538,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
   return py_obj.CreateStructuredObject();
 }
 
-StructuredData::GenericSP
-ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject(
-    const char *class_name, lldb::ProcessSP process_sp) {
-  if (class_name == nullptr || class_name[0] == '\0')
-    return StructuredData::GenericSP();
-
-  if (!process_sp)
-    return StructuredData::GenericSP();
-
-  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
-  PythonObject ret_val = SWIGBridge::LLDBSWIGPythonCreateOSPlugin(
-      class_name, m_dictionary_name.c_str(), process_sp);
-
-  return StructuredData::GenericSP(
-      new StructuredPythonObject(std::move(ret_val)));
-}
-
-StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo(
-    StructuredData::ObjectSP os_plugin_object_sp) {
-  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
-
-  if (!os_plugin_object_sp)
-    return {};
-
-  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
-  if (!generic)
-    return {};
-
-  PythonObject implementor(PyRefType::Borrowed,
-                           (PyObject *)generic->GetValue());
-
-  if (!implementor.IsAllocated())
-    return {};
-
-  llvm::Expected<PythonObject> expected_py_return =
-      implementor.CallMethod("get_register_info");
-
-  if (!expected_py_return) {
-    llvm::consumeError(expected_py_return.takeError());
-    return {};
-  }
-
-  PythonObject py_return = std::move(expected_py_return.get());
-
-  if (py_return.get()) {
-    PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
-    return result_dict.CreateStructuredDictionary();
-  }
-  return StructuredData::DictionarySP();
-}
-
-StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo(
-    StructuredData::ObjectSP os_plugin_object_sp) {
-  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
-  if (!os_plugin_object_sp)
-    return {};
-
-  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
-  if (!generic)
-    return {};
-
-  PythonObject implementor(PyRefType::Borrowed,
-                           (PyObject *)generic->GetValue());
-
-  if (!implementor.IsAllocated())
-    return {};
-
-  llvm::Expected<PythonObject> expected_py_return =
-      implementor.CallMethod("get_thread_info");
-
-  if (!expected_py_return) {
-    llvm::consumeError(expected_py_return.takeError());
-    return {};
-  }
-
-  PythonObject py_return = std::move(expected_py_return.get());
-
-  if (py_return.get()) {
-    PythonList result_list(PyRefType::Borrowed, py_return.get());
-    return result_list.CreateStructuredArray();
-  }
-  return StructuredData::ArraySP();
-}
-
-StructuredData::StringSP
-ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData(
-    StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) {
-  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
-
-  if (!os_plugin_object_sp)
-    return {};
-
-  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
-  if (!generic)
-    return {};
-  PythonObject implementor(PyRefType::Borrowed,
-                           (PyObject *)generic->GetValue());
-
-  if (!implementor.IsAllocated())
-    return {};
-
-  llvm::Expected<PythonObject> expected_py_return =
-      implementor.CallMethod("get_register_data", tid);
-
-  if (!expected_py_return) {
-    llvm::consumeError(expected_py_return.takeError());
-    return {};
-  }
-
-  PythonObject py_return = std::move(expected_py_return.get());
-
-  if (py_return.get()) {
-    PythonBytes result(PyRefType::Borrowed, py_return.get());
-    return result.CreateStructuredString();
-  }
-  return {};
-}
-
-StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread(
-    StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid,
-    lldb::addr_t context) {
-  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
-
-  if (!os_plugin_object_sp)
-    return {};
-
-  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
-  if (!generic)
-    return {};
-
-  PythonObject implementor(PyRefType::Borrowed,
-                           (PyObject *)generic->GetValue());
-
-  if (!implementor.IsAllocated())
-    return {};
-
-  llvm::Expected<PythonObject> expected_py_return =
-      implementor.CallMethod("create_thread", tid, context);
-
-  if (!expected_py_return) {
-    llvm::consumeError(expected_py_return.takeError());
-    return {};
-  }
-
-  PythonObject py_return = std::move(expected_py_return.get());
-
-  if (py_return.get()) {
-    PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
-    return result_dict.CreateStructuredDictionary();
-  }
-  return StructuredData::DictionarySP();
-}
-
 StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
     const char *class_name, const StructuredDataImpl &args_data,
     std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 00dc1d1baa309f6..a33499816d8d38c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -134,24 +134,9 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
 
   lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
 
-  StructuredData::GenericSP
-  OSPlugin_CreatePluginObject(const char *class_name,
-                              lldb::ProcessSP process_sp) override;
-
-  StructuredData::DictionarySP
-  OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
   lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
 
-  StructuredData::ArraySP
-  OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
-
-  StructuredData::StringSP
-  OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
-                               lldb::tid_t thread_id) override;
-
-  StructuredData::DictionarySP
-  OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
-                        lldb::tid_t tid, lldb::addr_t context) override;
+  lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override;
 
   StructuredData::ObjectSP
   LoadPluginModule(const FileSpec &file_spec,

>From 319f32998a530d256fe8a57418de8e3c4d115e17 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Fri, 1 Sep 2023 16:49:01 +0100
Subject: [PATCH 4/9] [lldb] Add OperatingSystem base class to the lldb python
 module

This patch introduces an `OperatingSystem` base implementation in the
`lldb` python module to make it easier for lldb users to write their own
implementation.

The `OperatingSystem` base implementation is derived itself from the
`ScriptedThread` base implementation since they share some common grounds.

To achieve that, this patch makes changes to the `ScriptedThread`
initializer since it gets called by the `OperatingSystem` initializer.

I also took the opportunity to document the `OperatingSystem` base
class and methods.

Differential Revision: https://reviews.llvm.org/D159315

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/CMakeLists.txt           |   3 +-
 .../python/templates/operating_system.py      | 103 ++++++++++++++++++
 .../python/templates/scripted_process.py      |  26 +++--
 .../python_os_plugin/operating_system.py      |  40 +------
 4 files changed, 124 insertions(+), 48 deletions(-)
 create mode 100644 lldb/examples/python/templates/operating_system.py

diff --git a/lldb/bindings/python/CMakeLists.txt b/lldb/bindings/python/CMakeLists.txt
index c4806bda27049c6..c941f764dfc92ac 100644
--- a/lldb/bindings/python/CMakeLists.txt
+++ b/lldb/bindings/python/CMakeLists.txt
@@ -104,7 +104,8 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar
     "plugins"
     FILES
     "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_process.py"
-    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py")
+    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py"
+    "${LLDB_SOURCE_DIR}/examples/python/templates/operating_system.py")
 
   if(APPLE)
     create_python_package(
diff --git a/lldb/examples/python/templates/operating_system.py b/lldb/examples/python/templates/operating_system.py
new file mode 100644
index 000000000000000..a8053bcaa21afe7
--- /dev/null
+++ b/lldb/examples/python/templates/operating_system.py
@@ -0,0 +1,103 @@
+from abc import abstractmethod
+
+import lldb
+import struct
+
+from lldb.plugins.scripted_process import ScriptedThread
+
+
+class OperatingSystem(ScriptedThread):
+    """
+    Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class.
+
+    ```
+    thread_info = {
+        "tid": tid,
+        "name": "four",
+        "queue": "queue4",
+        "state": "stopped",
+        "stop_reason": "none",
+        "core" : 2
+    }
+    ```
+
+    - tid : thread ID (mandatory)
+    - name : thread name (optional key/value pair)
+    - queue : thread dispatch queue name (optional key/value pair)
+    - state : thread state (mandatory, set to 'stopped' for now)
+    - core : the index of the core (lldb) thread that this OS Thread should shadow
+    - stop_reason : thread stop reason. (mandatory, usually set to 'none')
+        Possible values include:
+        - 'breakpoint': thread is stopped at a breakpoint
+        - 'none': thread is stopped because the process is stopped
+        - 'trace': thread is stopped after single stepping
+        The usual value for this while threads are in memory is 'none'
+    - register_data_addr : the address of the register data in memory (optional key/value pair)
+        Specifying this key/value pair for a thread will avoid a call to get_register_data()
+        and can be used when your registers are in a thread context structure that is contiguous
+        in memory. Don't specify this if your register layout in memory doesn't match the layout
+        described by the dictionary returned from a call to the get_register_info() method.
+    """
+
+    def __init__(self, process):
+        """Initialization needs a valid lldb.SBProcess object. This plug-in
+        will get created after a live process is valid and has stopped for the
+        first time.
+
+        Args:
+            process (lldb.SBProcess): The process owning this thread.
+        """
+        self.registers = None
+        super().__init__(process, None)
+        self.registers = self.register_info
+        self.threads = []
+
+    def create_thread(self, tid, context):
+        """Lazily create an operating system thread using a thread information
+        dictionary and an optional operating system thread context address.
+        This method is called manually, using the SBAPI
+        `lldb.SBProcess.CreateOSPluginThread` affordance.
+
+        Args:
+            tid (int): Thread ID to get `thread_info` dictionary for.
+            context (int): Address of the operating system thread struct.
+
+        Returns:
+            Dict: The `thread_info` dictionary containing the various information
+            for lldb to create a Thread object and add it to the process thread list.
+        """
+        return None
+
+    @abstractmethod
+    def get_thread_info(self):
+        """Get the list of operating system threads. This method gets called
+        automatically every time the process stops and it needs to update its
+        thread list.
+
+        Returns:
+            List[thread_info]: A list of `os_thread` dictionaries
+                containing at least for each entry, the thread id, it's name,
+                queue, state, stop reason. It can also contain a
+                `register_data_addr`. The list can be empty.
+        """
+        pass
+
+    @abstractmethod
+    def get_register_data(self, tid):
+        """Get the operating system thread register context for given a thread
+        id. This method is called when unwinding the stack of one of the
+        operating system threads.
+
+        Args:
+            tid (int): Thread ID to get register context for.
+
+        Returns:
+            str: A byte representing all register's value.
+        """
+        pass
+
+    def get_register_context(self):
+        pass
+
+    def get_stop_reason(self):
+        pass
diff --git a/lldb/examples/python/templates/scripted_process.py b/lldb/examples/python/templates/scripted_process.py
index d74ef02dec8591c..3ddcebd128eaa6e 100644
--- a/lldb/examples/python/templates/scripted_process.py
+++ b/lldb/examples/python/templates/scripted_process.py
@@ -244,16 +244,16 @@ class ScriptedThread(metaclass=ABCMeta):
     """
 
     @abstractmethod
-    def __init__(self, scripted_process, args):
+    def __init__(self, process, args):
         """Construct a scripted thread.
 
         Args:
-            process (ScriptedProcess): The scripted process owning this thread.
+            process (ScriptedProcess/lldb.SBProcess): The process owning this thread.
             args (lldb.SBStructuredData): A Dictionary holding arbitrary
                 key/value pairs used by the scripted thread.
         """
         self.target = None
-        self.scripted_process = None
+        self.originating_process = None
         self.process = None
         self.args = None
         self.idx = 0
@@ -268,9 +268,13 @@ def __init__(self, scripted_process, args):
         self.frames = []
         self.extended_info = []
 
-        if isinstance(scripted_process, ScriptedProcess):
-            self.target = scripted_process.target
-            self.scripted_process = scripted_process
+        if (
+            isinstance(process, ScriptedProcess)
+            or isinstance(process, lldb.SBProcess)
+            and process.IsValid()
+        ):
+            self.target = process.target
+            self.originating_process = process
             self.process = self.target.GetProcess()
             self.get_register_info()
 
@@ -354,14 +358,14 @@ def get_stackframes(self):
     def get_register_info(self):
         if self.register_info is None:
             self.register_info = dict()
-            if self.scripted_process.arch == "x86_64":
+            if self.originating_process.arch == "x86_64":
                 self.register_info["sets"] = ["General Purpose Registers"]
                 self.register_info["registers"] = INTEL64_GPR
-            elif "arm64" in self.scripted_process.arch:
+            elif "arm64" in self.originating_process.arch:
                 self.register_info["sets"] = ["General Purpose Registers"]
                 self.register_info["registers"] = ARM64_GPR
             else:
-                raise ValueError("Unknown architecture", self.scripted_process.arch)
+                raise ValueError("Unknown architecture", self.originating_process.arch)
         return self.register_info
 
     @abstractmethod
@@ -505,12 +509,12 @@ def get_stop_reason(self):
 
             # TODO: Passthrough stop reason from driving process
             if self.driving_thread.GetStopReason() != lldb.eStopReasonNone:
-                if "arm64" in self.scripted_process.arch:
+                if "arm64" in self.originating_process.arch:
                     stop_reason["type"] = lldb.eStopReasonException
                     stop_reason["data"][
                         "desc"
                     ] = self.driving_thread.GetStopDescription(100)
-                elif self.scripted_process.arch == "x86_64":
+                elif self.originating_process.arch == "x86_64":
                     stop_reason["type"] = lldb.eStopReasonSignal
                     stop_reason["data"]["signal"] = signal.SIGTRAP
                 else:
diff --git a/lldb/test/API/functionalities/plugins/python_os_plugin/operating_system.py b/lldb/test/API/functionalities/plugins/python_os_plugin/operating_system.py
index 52c678fac2efedf..f4404d78492f98d 100644
--- a/lldb/test/API/functionalities/plugins/python_os_plugin/operating_system.py
+++ b/lldb/test/API/functionalities/plugins/python_os_plugin/operating_system.py
@@ -1,29 +1,14 @@
-#!/usr/bin/env python
-
 import lldb
 import struct
 
+from lldb.plugins.operating_system import OperatingSystem
+
 
-class OperatingSystemPlugIn(object):
+class OperatingSystemPlugIn(OperatingSystem):
     """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
 
     def __init__(self, process):
-        """Initialization needs a valid.SBProcess object.
-
-        This plug-in will get created after a live process is valid and has stopped for the
-        first time."""
-        self.process = None
-        self.registers = None
-        self.threads = None
-        if isinstance(process, lldb.SBProcess) and process.IsValid():
-            self.process = process
-            self.threads = None  # Will be an dictionary containing info for each thread
-
-    def get_target(self):
-        # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target"
-        # tracks the current target in the LLDB command interpreter which isn't the
-        # correct thing to use for this plug-in.
-        return self.process.target
+        super().__init__(process)
 
     def create_thread(self, tid, context):
         if tid == 0x444444444:
@@ -40,23 +25,6 @@ def create_thread(self, tid, context):
 
     def get_thread_info(self):
         if not self.threads:
-            # The sample dictionary below shows the values that can be returned for a thread
-            # tid => thread ID (mandatory)
-            # name => thread name (optional key/value pair)
-            # queue => thread dispatch queue name (optional key/value pair)
-            # state => thred state (mandatory, set to 'stopped' for now)
-            # stop_reason => thread stop reason. (mandatory, usually set to 'none')
-            #  Possible values include:
-            #   'breakpoint' if the thread is stopped at a breakpoint
-            #   'none' thread is just stopped because the process is stopped
-            #   'trace' the thread just single stepped
-            #   The usual value for this while threads are in memory is 'none'
-            # register_data_addr => the address of the register data in memory (optional key/value pair)
-            #   Specifying this key/value pair for a thread will avoid a call to get_register_data()
-            #   and can be used when your registers are in a thread context structure that is contiguous
-            #   in memory. Don't specify this if your register layout in memory doesn't match the layout
-            # described by the dictionary returned from a call to the
-            # get_register_info() method.
             self.threads = [
                 {
                     "tid": 0x111111111,

>From 02ad2756d310e64f97eeccf131d95c3d5656ba6a Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Sat, 26 Aug 2023 00:44:38 +0100
Subject: [PATCH 5/9] [lldb/docs] Add OperatingSystem documentation to the
 website

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/docs/use/python.rst | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lldb/docs/use/python.rst b/lldb/docs/use/python.rst
index 6183d6935d80ef8..83e10b9df619bf6 100644
--- a/lldb/docs/use/python.rst
+++ b/lldb/docs/use/python.rst
@@ -11,6 +11,15 @@ some of these things by going through an example, explaining how to use
 Python scripting to find a bug in a program that searches for text in a
 large binary tree.
 
+Operating System Thread Plugins
+-------------------------------
+
+.. literalinclude:: ../../examples/python/templates/operating_system.py
+   :language: python
+   :linenos:
+   :encoding: utf-8
+   :pyobject: OperatingSystem
+
 The Test Program and Input
 --------------------------
 

>From a6e352ba064f02beff31558fad82755907bd057d Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Wed, 18 Oct 2023 14:28:32 -0700
Subject: [PATCH 6/9] [lldb] Add new interface for ScriptedThreadPlan

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/python-wrapper.swig      | 127 ------------------
 .../Interfaces/ScriptedInterface.h            |  13 +-
 .../Interfaces/ScriptedPlatformInterface.h    |   4 +-
 .../Interfaces/ScriptedProcessInterface.h     |   6 +-
 .../Interfaces/ScriptedThreadInterface.h      |   8 +-
 .../Interfaces/ScriptedThreadPlanInterface.h  |  38 ++++++
 .../lldb/Interpreter/ScriptInterpreter.h      |  49 +------
 lldb/include/lldb/Target/ThreadPlanPython.h   |   2 +
 lldb/include/lldb/lldb-forward.h              |   3 +
 .../Python/OperatingSystemPython.cpp          |   3 +-
 .../Process/scripted/ScriptedProcess.cpp      |   4 +-
 .../Process/scripted/ScriptedThread.cpp       |   4 +-
 .../Python/Interfaces/CMakeLists.txt          |   1 +
 .../OperatingSystemPythonInterface.cpp        |  17 +--
 .../OperatingSystemPythonInterface.h          |   2 +-
 .../ScriptedPlatformPythonInterface.cpp       |  25 ----
 .../ScriptedPlatformPythonInterface.h         |   6 -
 .../ScriptedProcessPythonInterface.cpp        |  24 +---
 .../ScriptedProcessPythonInterface.h          |   8 +-
 .../Interfaces/ScriptedPythonInterface.h      |  88 ++++++++++++
 .../ScriptedThreadPlanPythonInterface.cpp     |  89 ++++++++++++
 .../ScriptedThreadPlanPythonInterface.h       |  45 +++++++
 .../ScriptedThreadPythonInterface.cpp         |  32 +----
 .../ScriptedThreadPythonInterface.h           |   2 +-
 .../Python/SWIGPythonBridge.h                 |  15 ---
 .../Python/ScriptInterpreterPython.cpp        | 122 +----------------
 .../Python/ScriptInterpreterPythonImpl.h      |  27 +---
 lldb/source/Target/ThreadPlanPython.cpp       |  57 ++++----
 .../functionalities/step_scripted/Steps.py    |   4 +-
 .../Python/PythonTestSuite.cpp                |  20 ---
 30 files changed, 349 insertions(+), 496 deletions(-)
 create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
 create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
 create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h

diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 758fdf6c80c0029..a1e2febaf209c25 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -281,133 +281,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedObjec
   return result;
 }
 
-PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan(
-    const char *python_class_name, const char *session_dictionary_name,
-    const lldb_private::StructuredDataImpl &args_impl,
-    std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp) {
-  if (python_class_name == NULL || python_class_name[0] == '\0' ||
-      !session_dictionary_name)
-    return PythonObject();
-
-  PyErr_Cleaner py_err_cleaner(true);
-
-  auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
-      session_dictionary_name);
-  auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
-      python_class_name, dict);
-
-  if (!pfunc.IsAllocated()) {
-    error_string.append("could not find script class: ");
-    error_string.append(python_class_name);
-    return PythonObject();
-  }
-
-  PythonObject tp_arg = SWIGBridge::ToSWIGWrapper(thread_plan_sp);
-
-  llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
-  if (!arg_info) {
-    llvm::handleAllErrors(
-        arg_info.takeError(),
-        [&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
-        [&](const llvm::ErrorInfoBase &E) {
-          error_string.append(E.message());
-        });
-    return PythonObject();
-  }
-
-  PythonObject result = {};
-  auto args_sb = std::unique_ptr<lldb::SBStructuredData>(new lldb::SBStructuredData(args_impl));
-  if (arg_info.get().max_positional_args == 2) {
-    if (args_sb->IsValid()) {
-      error_string.assign(
-          "args passed, but __init__ does not take an args dictionary");
-      return PythonObject();
-    }
-    result = pfunc(tp_arg, dict);
-  } else if (arg_info.get().max_positional_args >= 3) {
-    result = pfunc(tp_arg, SWIGBridge::ToSWIGWrapper(std::move(args_sb)), dict);
-  } else {
-    error_string.assign("wrong number of arguments in __init__, should be 2 or "
-                        "3 (not including self)");
-    return PythonObject();
-  }
-
-  // FIXME: At this point we should check that the class we found supports all
-  // the methods that we need.
-
-  return result;
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-    void *implementor, const char *method_name, lldb_private::Event *event,
-    bool &got_error) {
-  got_error = false;
-
-  PyErr_Cleaner py_err_cleaner(false);
-  PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
-  auto pfunc = self.ResolveName<PythonCallable>(method_name);
-
-  if (!pfunc.IsAllocated())
-    return false;
-
-  PythonObject result;
-  if (event != nullptr) {
-    ScopedPythonObject<SBEvent> event_arg = SWIGBridge::ToSWIGWrapper(event);
-    result = pfunc(event_arg.obj());
-  } else
-    result = pfunc();
-
-  if (PyErr_Occurred()) {
-    got_error = true;
-    printf("Return value was neither false nor true for call to %s.\n",
-           method_name);
-    PyErr_Print();
-    return false;
-  }
-
-  if (result.get() == Py_True)
-    return true;
-  else if (result.get() == Py_False)
-    return false;
-
-  // Somebody returned the wrong thing...
-  got_error = true;
-  printf("Wrong return value type for call to %s.\n", method_name);
-  return false;
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-    void *implementor, const char *method_name, lldb_private::Stream *stream,
-    bool &got_error) {
-  got_error = false;
-
-  PyErr_Cleaner py_err_cleaner(false);
-  PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
-  auto pfunc = self.ResolveName<PythonCallable>(method_name);
-
-  if (!pfunc.IsAllocated()) 
-    return false;
-
-  auto *sb_stream = new lldb::SBStream();
-  PythonObject sb_stream_arg =
-      SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream>(sb_stream));
-
-  PythonObject result;
-  result = pfunc(sb_stream_arg);
-
-  if (PyErr_Occurred()) {
-    printf("Error occured for call to %s.\n",
-           method_name);
-    PyErr_Print();
-    got_error = true;
-    return false;
-  }
-  if (stream)
-    stream->PutCString(sb_stream->GetData());
-  return true;
-
-}
-
 PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
     const char *python_class_name, const char *session_dictionary_name,
     const StructuredDataImpl &args_impl,
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
index 948f763e95ecea4..32222185c100ded 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
@@ -10,14 +10,8 @@
 #define LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
 
 #include "lldb/Core/StructuredDataImpl.h"
-#include "lldb/Target/ExecutionContext.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
-#include "lldb/lldb-private.h"
-
-#include "llvm/Support/Compiler.h"
-
-#include <string>
 
 namespace lldb_private {
 class ScriptedInterface {
@@ -25,11 +19,6 @@ class ScriptedInterface {
   ScriptedInterface() = default;
   virtual ~ScriptedInterface() = default;
 
-  virtual StructuredData::GenericSP
-  CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
-                     StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) = 0;
-
   StructuredData::GenericSP GetScriptObjectInstance() {
     return m_object_instance_sp;
   }
@@ -54,7 +43,7 @@ class ScriptedInterface {
   }
 
   template <typename T = StructuredData::ObjectSP>
-  bool CheckStructuredDataObject(llvm::StringRef caller, T obj, Status &error) {
+  static bool CheckStructuredDataObject(llvm::StringRef caller, T obj, Status &error) {
     if (!obj)
       return ErrorWithMessage<bool>(caller, "Null Structured Data object",
                                     error);
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
index c687cabfe0c1278..ca25f3304aac898 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h
@@ -22,10 +22,10 @@ class ScriptedPlatformInterface : virtual public ScriptedInterface {
   StructuredData::GenericSP
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override {
+                     StructuredData::Generic *script_obj = nullptr) {
     return {};
   }
-
+  
   virtual StructuredData::DictionarySP ListProcesses() { return {}; }
 
   virtual StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) {
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
index 68756c4d9ac858d..5a030f29907ffb6 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
@@ -21,13 +21,13 @@
 namespace lldb_private {
 class ScriptedProcessInterface : virtual public ScriptedInterface {
 public:
-  StructuredData::GenericSP
+  virtual StructuredData::GenericSP
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override {
+                     StructuredData::Generic *script_obj = nullptr) {
     return {};
   }
-
+  
   virtual StructuredData::DictionarySP GetCapabilities() { return {}; }
 
   virtual Status Attach(const ProcessAttachInfo &attach_info) {
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
index 781df51a213229a..3cb3d7b231c68e3 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
@@ -18,15 +18,15 @@
 #include <string>
 
 namespace lldb_private {
-class ScriptedThreadInterface : virtual public ScriptedInterface {
+class ScriptedThreadInterface : public ScriptedInterface {
 public:
-  StructuredData::GenericSP
+  virtual StructuredData::GenericSP
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override {
+                     StructuredData::Generic *script_obj = nullptr) {
     return {};
   }
-
+  
   virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; }
 
   virtual std::optional<std::string> GetName() { return std::nullopt; }
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
new file mode 100644
index 000000000000000..972254e1fd4d89f
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
@@ -0,0 +1,38 @@
+//===-- ScriptedThreadInterface.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H
+
+#include "lldb/lldb-private.h"
+
+#include "ScriptedInterface.h"
+
+namespace lldb_private {
+class ScriptedThreadPlanInterface : public ScriptedInterface {
+public:
+  virtual StructuredData::GenericSP
+  CreatePluginObject(llvm::StringRef class_name,
+                     lldb::ThreadPlanSP thread_plan_sp,
+                     const StructuredDataImpl& args_sp) {
+    return {};
+  }
+  
+  virtual bool ExplainsStop(Event *event) { return true; }
+
+  virtual bool ShouldStop(Event *event) { return true; }
+
+  virtual bool IsStale() { return true; };
+
+  virtual lldb::StateType GetRunState() { return lldb::eStateStepping; }
+
+  virtual bool GetStopDescription(lldb_private::Stream *s) { return true; }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 57a1962441e9510..73827bd0f2953c5 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -25,6 +25,7 @@
 #include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
 #include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
 #include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
 #include "lldb/Interpreter/ScriptObject.h"
 #include "lldb/Utility/Broadcaster.h"
 #include "lldb/Utility/Status.h"
@@ -275,50 +276,6 @@ class ScriptInterpreter : public PluginInterface {
     return StructuredData::DictionarySP();
   }
 
-  virtual StructuredData::ObjectSP
-  CreateScriptedThreadPlan(const char *class_name,
-                           const StructuredDataImpl &args_data,
-                           std::string &error_str,
-                           lldb::ThreadPlanSP thread_plan_sp) {
-    return StructuredData::ObjectSP();
-  }
-
-  virtual bool
-  ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
-                                 Event *event, bool &script_error) {
-    script_error = true;
-    return true;
-  }
-
-  virtual bool
-  ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
-                               Event *event, bool &script_error) {
-    script_error = true;
-    return true;
-  }
-
-  virtual bool
-  ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
-                            bool &script_error) {
-    script_error = true;
-    return true;
-  }
-
-  virtual lldb::StateType
-  ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
-                                bool &script_error) {
-    script_error = true;
-    return lldb::eStateStepping;
-  }
-
-  virtual bool
-  ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp,
-                                       lldb_private::Stream *stream,
-                                       bool &script_error) {
-    script_error = true;
-    return false;
-  }
-
   virtual StructuredData::GenericSP
   CreateScriptedBreakpointResolver(const char *class_name,
                                    const StructuredDataImpl &args_data,
@@ -587,6 +544,10 @@ class ScriptInterpreter : public PluginInterface {
   virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() {
     return std::make_shared<ScriptedThreadInterface>();
   }
+  
+  virtual lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() {
+    return std::make_shared<ScriptedThreadPlanInterface>();
+  }
 
   virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() {
     return std::make_shared<OperatingSystemInterface>();
diff --git a/lldb/include/lldb/Target/ThreadPlanPython.h b/lldb/include/lldb/Target/ThreadPlanPython.h
index 64854d66b8f2589..da106faf951db1c 100644
--- a/lldb/include/lldb/Target/ThreadPlanPython.h
+++ b/lldb/include/lldb/Target/ThreadPlanPython.h
@@ -13,6 +13,7 @@
 #include <string>
 
 #include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
@@ -70,6 +71,7 @@ class ThreadPlanPython : public ThreadPlan {
   StreamString m_stop_description; // Cache the stop description here
   bool m_did_push;
   bool m_stop_others;
+  lldb::ScriptedThreadPlanInterfaceSP m_interface;
 
   ThreadPlanPython(const ThreadPlanPython &) = delete;
   const ThreadPlanPython &operator=(const ThreadPlanPython &) = delete;
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index aa099d4abc3b09f..6138e6fe5a60b45 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -185,6 +185,7 @@ class ScriptedMetadata;
 class ScriptedPlatformInterface;
 class ScriptedProcessInterface;
 class ScriptedThreadInterface;
+class ScriptedThreadPlanInterface;
 class ScriptedSyntheticChildren;
 class SearchFilter;
 class Section;
@@ -393,6 +394,8 @@ typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>
     ScriptedProcessInterfaceUP;
 typedef std::shared_ptr<lldb_private::ScriptedThreadInterface>
     ScriptedThreadInterfaceSP;
+typedef std::shared_ptr<lldb_private::ScriptedThreadPlanInterface>
+    ScriptedThreadPlanInterfaceSP;
 typedef std::shared_ptr<lldb_private::Section> SectionSP;
 typedef std::unique_ptr<lldb_private::SectionList> SectionListUP;
 typedef std::weak_ptr<lldb_private::Section> SectionWP;
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 9a5dd515489231c..96861b2a20dc869 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -116,8 +116,7 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
 
   ExecutionContext exe_ctx(process);
   StructuredData::GenericSP owned_script_object_sp =
-      operating_system_interface->CreatePluginObject(os_plugin_class_name,
-                                                     exe_ctx, nullptr);
+      operating_system_interface->CreatePluginObject(os_plugin_class_name, exe_ctx, nullptr);
 
   if (!owned_script_object_sp)
     //    return llvm::createStringError(llvm::inconvertibleErrorCode(),
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index e99a2a08bd50d8f..0990506f1117fb6 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -108,9 +108,7 @@ ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
   ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
 
   // Create process script object
-  StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
-      m_scripted_metadata.GetClassName(), exe_ctx,
-      m_scripted_metadata.GetArgsSP());
+  StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(m_scripted_metadata.GetClassName(), exe_ctx, m_scripted_metadata.GetArgsSP());
 
   if (!object_sp || !object_sp->IsValid()) {
     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index 684375957d24760..105446ae55a0b60 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -58,8 +58,8 @@ ScriptedThread::Create(ScriptedProcess &process,
   ExecutionContext exe_ctx(process);
   StructuredData::GenericSP owned_script_object_sp =
       scripted_thread_interface->CreatePluginObject(
-          thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(),
-          script_object);
+          thread_class_name,
+          exe_ctx, process.m_scripted_metadata.GetArgsSP(), script_object);
 
   if (!owned_script_object_sp)
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
index b22abc49c92a9a9..c60e4bb503a3710 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
@@ -24,6 +24,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
   ScriptedPythonInterface.cpp
   ScriptedProcessPythonInterface.cpp
   ScriptedThreadPythonInterface.cpp
+  ScriptedThreadPlanPythonInterface.cpp
   ScriptedPlatformPythonInterface.cpp
 
   LINK_LIBS
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
index 45804d5d019d79d..0defa0ec00eba46 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/Config.h"
+#include "lldb/Target/ExecutionContext.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/lldb-enumerations.h"
 
@@ -28,11 +29,11 @@ OperatingSystemPythonInterface::OperatingSystemPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {}
 
-StructuredData::GenericSP OperatingSystemPythonInterface::CreatePluginObject(
-    llvm::StringRef class_name, ExecutionContext &exe_ctx,
-    StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
-  return ScriptedThreadPythonInterface::CreatePluginObject(class_name, exe_ctx,
-                                                           args_sp, script_obj);
+StructuredData::GenericSP
+OperatingSystemPythonInterface::CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
+                                                   StructuredData::DictionarySP args_sp,
+                                                   StructuredData::Generic *script_obj) {
+  return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, exe_ctx.GetProcessSP());
 }
 
 StructuredData::DictionarySP
@@ -42,7 +43,7 @@ OperatingSystemPythonInterface::CreateThread(lldb::tid_t tid,
   StructuredData::DictionarySP dict = Dispatch<StructuredData::DictionarySP>(
       "create_thread", error, tid, context);
 
-  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
+  if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
     return {};
 
   return dict;
@@ -53,7 +54,7 @@ StructuredData::ArraySP OperatingSystemPythonInterface::GetThreadInfo() {
   StructuredData::ArraySP arr =
       Dispatch<StructuredData::ArraySP>("get_thread_info", error);
 
-  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
+  if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
     return {};
 
   return arr;
@@ -68,7 +69,7 @@ OperatingSystemPythonInterface::GetRegisterContextForTID(lldb::tid_t tid) {
   Status error;
   StructuredData::ObjectSP obj = Dispatch("get_register_data", error, tid);
 
-  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+  if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
     return {};
 
   return obj->GetAsString()->GetValue().str();
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
index a69557ad7c43469..323cebf5b919eff 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
@@ -23,7 +23,7 @@ class OperatingSystemPythonInterface
       virtual public ScriptedThreadPythonInterface {
 public:
   OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-
+        
   StructuredData::GenericSP
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
index 9bed33516915d08..f2a65583927d4af 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp
@@ -29,31 +29,6 @@ ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {}
 
-StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject(
-    llvm::StringRef class_name, ExecutionContext &exe_ctx,
-    StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
-  if (class_name.empty())
-    return {};
-
-  StructuredDataImpl args_impl(args_sp);
-  std::string error_string;
-
-  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                 Locker::FreeLock);
-
-  lldb::ExecutionContextRefSP exe_ctx_ref_sp =
-      std::make_shared<ExecutionContextRef>(exe_ctx);
-
-  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject(
-      class_name.str().c_str(), m_interpreter.GetDictionaryName(),
-      exe_ctx_ref_sp, args_impl, error_string);
-
-  m_object_instance_sp =
-      StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
-
-  return m_object_instance_sp;
-}
-
 StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() {
   Status error;
   StructuredData::DictionarySP dict_sp =
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
index 02deecd15ede062..fc632cd3e7f1dc1 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h
@@ -22,12 +22,6 @@ class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface,
 public:
   ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter);
 
-  StructuredData::GenericSP
-  CreatePluginObject(const llvm::StringRef class_name,
-                     ExecutionContext &exe_ctx,
-                     StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override;
-
   StructuredData::DictionarySP ListProcesses() override;
 
   StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
index 63a4db1ff5973e7..a251df5d51ce108 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
@@ -32,30 +32,12 @@ using Locker = ScriptInterpreterPythonImpl::Locker;
 ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
-
 StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
     llvm::StringRef class_name, ExecutionContext &exe_ctx,
     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
-  if (class_name.empty())
-    return {};
-
-  StructuredDataImpl args_impl(args_sp);
-  std::string error_string;
-
-  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                 Locker::FreeLock);
-
-  lldb::ExecutionContextRefSP exe_ctx_ref_sp =
-      std::make_shared<ExecutionContextRef>(exe_ctx);
-
-  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject(
-      class_name.str().c_str(), m_interpreter.GetDictionaryName(),
-      exe_ctx_ref_sp, args_impl, error_string);
-
-  m_object_instance_sp =
-      StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
-
-  return m_object_instance_sp;
+  ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);
+  StructuredDataImpl sd_impl(args_sp);
+  return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, exe_ctx_ref_sp, sd_impl);
 }
 
 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
index 11330f5591b74e6..6dda8c812e94281 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
@@ -22,12 +22,12 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
                                        public ScriptedPythonInterface {
 public:
   ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-
+                                         
   StructuredData::GenericSP
   CreatePluginObject(const llvm::StringRef class_name,
-                     ExecutionContext &exe_ctx,
-                     StructuredData::DictionarySP args_sp,
-                     StructuredData::Generic *script_obj = nullptr) override;
+                    ExecutionContext &exe_ctx,
+                    StructuredData::DictionarySP args_sp,
+                    StructuredData::Generic *script_obj = nullptr) override;
 
   StructuredData::DictionarySP GetCapabilities() override;
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 9163b8f6aede7d1..efd34496846b72b 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -31,6 +31,78 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
 public:
   ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter);
   ~ScriptedPythonInterface() override = default;
+  
+  template <typename ...Args>
+  StructuredData::GenericSP
+  CreatePluginObject(llvm::StringRef class_name,
+                     StructuredData::Generic *script_obj, Args ...args) {
+    using namespace python;
+    using Locker = ScriptInterpreterPythonImpl::Locker;
+    
+    std::string error_string;
+    if (class_name.empty() && llvm::StringRef(m_interpreter.GetDictionaryName()).empty() && !script_obj)
+      return {};
+
+    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+                   Locker::FreeLock);
+    
+    PythonObject result = {};
+    
+    if (!script_obj) {
+      auto dict = PythonModule::MainModule().ResolveName<python::PythonDictionary>(m_interpreter.GetDictionaryName());
+      auto pfunc = PythonObject::ResolveNameWithDictionary<python::PythonCallable>(class_name, dict);
+
+      if (!pfunc.IsAllocated()) {
+        error_string.append("could not find script class: ");
+        error_string.append(class_name);
+        return {};
+      }
+      
+      std::tuple<Args...> original_args = std::forward_as_tuple(args...);
+      auto transformed_args = TransformArgs(original_args);
+
+      llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
+      if (!arg_info) {
+        llvm::handleAllErrors(
+            arg_info.takeError(),
+                              [&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
+            [&](const llvm::ErrorInfoBase &E) {
+              error_string.append(E.message());
+            });
+        return {};
+      }
+      
+      llvm::Expected<PythonObject> expected_return_object =
+          llvm::make_error<llvm::StringError>("Not initialized.",
+                                              llvm::inconvertibleErrorCode());
+      
+      std::apply(
+          [&pfunc, &expected_return_object](auto &&...args) {
+            llvm::consumeError(expected_return_object.takeError());
+            expected_return_object = pfunc(args...);
+          },
+          transformed_args);
+      
+      if (llvm::Error e = expected_return_object.takeError()) {
+        error_string.append(llvm::toString(std::move(e)));
+        return {};
+  //      return ErrorWithMessage<T>(caller_signature,
+  //                                 "Python method could not be called.", error);
+      }
+
+      result = std::move(expected_return_object.get());
+      
+    } else
+      result = PythonObject(PyRefType::Borrowed,
+                             static_cast<PyObject *>(script_obj->GetValue()));
+      
+    
+    if (!result.IsValid())
+      return {};
+
+    m_object_instance_sp = StructuredData::GenericSP(new StructuredPythonObject(std::move(result)));
+    return m_object_instance_sp;
+  }
 
 protected:
   template <typename T = StructuredData::ObjectSP>
@@ -121,6 +193,22 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
   python::PythonObject Transform(Status arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
+  
+  python::PythonObject Transform(const StructuredDataImpl &arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+  
+  python::PythonObject Transform(lldb::ExecutionContextRefSP arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+  
+  python::PythonObject Transform(lldb::ProcessSP arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+  
+  python::PythonObject Transform(lldb::ThreadPlanSP arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
 
   python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
new file mode 100644
index 000000000000000..3f5f626e4b9e7b3
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
@@ -0,0 +1,89 @@
+//===-- ScriptedThreadPlanPythonInterface.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Config.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "../lldb-python.h"
+
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
+#include "ScriptedThreadPlanPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+
+ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface(
+    ScriptInterpreterPythonImpl &interpreter)
+    : ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {}
+
+
+StructuredData::GenericSP ScriptedThreadPlanPythonInterface::CreatePluginObject(
+                                                                            const llvm::StringRef class_name,
+                                                                                               lldb::ThreadPlanSP thread_plan_sp,
+                                                                                const StructuredDataImpl& args_sp) {
+  // FIXME: Not working
+  return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, thread_plan_sp, args_sp);
+}
+
+bool ScriptedThreadPlanPythonInterface::ExplainsStop(Event *event) {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("explains_stop", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return false;
+
+  return obj->GetBooleanValue();
+}
+
+bool ScriptedThreadPlanPythonInterface::ShouldStop(Event *event) {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("should_stop", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return false;
+
+  return obj->GetBooleanValue();
+}
+
+bool ScriptedThreadPlanPythonInterface::IsStale() {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("is_stale", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return false;
+
+  return obj->GetBooleanValue();
+}
+
+lldb::StateType ScriptedThreadPlanPythonInterface::GetRunState() {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("should_step", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return lldb::eStateStepping;
+
+  return static_cast<lldb::StateType>(obj->GetUnsignedIntegerValue(static_cast<uint32_t>(lldb::eStateStepping)));
+}
+
+bool ScriptedThreadPlanPythonInterface::GetStopDescription(lldb_private::Stream *s) {
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("stop_description", error);
+
+  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
+    return false;
+
+  return obj->GetBooleanValue();
+}
+
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
new file mode 100644
index 000000000000000..9ec6f36bc4b1797
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
@@ -0,0 +1,45 @@
+//===-- ScriptedThreadPlanPythonInterface.h ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "ScriptedPythonInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
+#include <optional>
+
+namespace lldb_private {
+class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface,
+                                          public ScriptedPythonInterface {
+public:
+  ScriptedThreadPlanPythonInterface(ScriptInterpreterPythonImpl &interpreter);
+                                      
+  StructuredData::GenericSP
+  CreatePluginObject(const llvm::StringRef class_name,
+                     lldb::ThreadPlanSP thread_plan_sp,
+                     const StructuredDataImpl& args_sp) override;
+                                        
+  bool ExplainsStop(Event *event) override;
+
+  bool ShouldStop(Event *event) override;
+
+  bool IsStale() override;
+
+  lldb::StateType GetRunState() override;
+
+  bool GetStopDescription(lldb_private::Stream *s) override;
+
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
index 6addcd46e045efc..63a32512e47feda 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/Config.h"
+#include "lldb/Target/ExecutionContext.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/lldb-enumerations.h"
 
@@ -32,34 +33,9 @@ ScriptedThreadPythonInterface::ScriptedThreadPythonInterface(
 StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject(
     const llvm::StringRef class_name, ExecutionContext &exe_ctx,
     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
-  if (class_name.empty() && !script_obj)
-    return {};
-
-  StructuredDataImpl args_impl(args_sp);
-  std::string error_string;
-
-  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                 Locker::FreeLock);
-
-  PythonObject ret_val;
-
-  if (!script_obj) {
-    lldb::ExecutionContextRefSP exe_ctx_ref_sp =
-        std::make_shared<ExecutionContextRef>(exe_ctx);
-    ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject(
-        class_name.str().c_str(), m_interpreter.GetDictionaryName(),
-        exe_ctx_ref_sp, args_impl, error_string);
-  } else
-    ret_val = PythonObject(PyRefType::Borrowed,
-                           static_cast<PyObject *>(script_obj->GetValue()));
-
-  if (!ret_val)
-    return {};
-
-  m_object_instance_sp =
-      StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
-
-  return m_object_instance_sp;
+  ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);
+  StructuredDataImpl sd_impl(args_sp);
+  return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, exe_ctx_ref_sp, sd_impl);
 }
 
 lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
index b63760fd5b5713d..d7b60d4beff9b5d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
@@ -22,7 +22,7 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface,
                                       public ScriptedPythonInterface {
 public:
   ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-
+                                      
   StructuredData::GenericSP
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 630ab293cf939ea..032df4f37a4081d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -152,21 +152,6 @@ class SWIGBridge {
                                     const char *session_dictionary_name,
                                     lldb::DebuggerSP debugger_sp);
 
-  static python::PythonObject LLDBSwigPythonCreateScriptedThreadPlan(
-      const char *python_class_name, const char *session_dictionary_name,
-      const StructuredDataImpl &args_data, std::string &error_string,
-      const lldb::ThreadPlanSP &thread_plan_sp);
-
-  static bool LLDBSWIGPythonCallThreadPlan(void *implementor,
-                                           const char *method_name,
-                                           lldb_private::Event *event_sp,
-                                           bool &got_error);
-
-  static bool LLDBSWIGPythonCallThreadPlan(void *implementor,
-                                           const char *method_name,
-                                           lldb_private::Stream *stream,
-                                           bool &got_error);
-
   static python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver(
       const char *python_class_name, const char *session_dictionary_name,
       const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index a57c8e4984ad8a8..87a1077dabdf62c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -18,6 +18,7 @@
 #include "Interfaces/ScriptedPlatformPythonInterface.h"
 #include "Interfaces/ScriptedProcessPythonInterface.h"
 #include "Interfaces/ScriptedThreadPythonInterface.h"
+#include "Interfaces/ScriptedThreadPlanPythonInterface.h"
 #include "PythonDataObjects.h"
 #include "PythonReadline.h"
 #include "SWIGPythonBridge.h"
@@ -1522,6 +1523,11 @@ ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
   return std::make_shared<ScriptedThreadPythonInterface>(*this);
 }
 
+ScriptedThreadPlanInterfaceSP
+ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {
+  return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
+}
+
 OperatingSystemInterfaceSP
 ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {
   return std::make_shared<OperatingSystemPythonInterface>(*this);
@@ -1538,122 +1544,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
   return py_obj.CreateStructuredObject();
 }
 
-StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
-    const char *class_name, const StructuredDataImpl &args_data,
-    std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
-  if (class_name == nullptr || class_name[0] == '\0')
-    return StructuredData::ObjectSP();
-
-  if (!thread_plan_sp.get())
-    return {};
-
-  Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
-  ScriptInterpreterPythonImpl *python_interpreter =
-      GetPythonInterpreter(debugger);
-
-  if (!python_interpreter)
-    return {};
-
-  Locker py_lock(this,
-                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan(
-      class_name, python_interpreter->m_dictionary_name.c_str(), args_data,
-      error_str, thread_plan_sp);
-  if (!ret_val)
-    return {};
-
-  return StructuredData::ObjectSP(
-      new StructuredPythonObject(std::move(ret_val)));
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop(
-    StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
-  bool explains_stop = true;
-  StructuredData::Generic *generic = nullptr;
-  if (implementor_sp)
-    generic = implementor_sp->GetAsGeneric();
-  if (generic) {
-    Locker py_lock(this,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-    explains_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-        generic->GetValue(), "explains_stop", event, script_error);
-    if (script_error)
-      return true;
-  }
-  return explains_stop;
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop(
-    StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
-  bool should_stop = true;
-  StructuredData::Generic *generic = nullptr;
-  if (implementor_sp)
-    generic = implementor_sp->GetAsGeneric();
-  if (generic) {
-    Locker py_lock(this,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-    should_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-        generic->GetValue(), "should_stop", event, script_error);
-    if (script_error)
-      return true;
-  }
-  return should_stop;
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale(
-    StructuredData::ObjectSP implementor_sp, bool &script_error) {
-  bool is_stale = true;
-  StructuredData::Generic *generic = nullptr;
-  if (implementor_sp)
-    generic = implementor_sp->GetAsGeneric();
-  if (generic) {
-    Locker py_lock(this,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-    is_stale = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-        generic->GetValue(), "is_stale", (Event *)nullptr, script_error);
-    if (script_error)
-      return true;
-  }
-  return is_stale;
-}
-
-lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState(
-    StructuredData::ObjectSP implementor_sp, bool &script_error) {
-  bool should_step = false;
-  StructuredData::Generic *generic = nullptr;
-  if (implementor_sp)
-    generic = implementor_sp->GetAsGeneric();
-  if (generic) {
-    Locker py_lock(this,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-    should_step = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-        generic->GetValue(), "should_step", (Event *)nullptr, script_error);
-    if (script_error)
-      should_step = true;
-  }
-  if (should_step)
-    return lldb::eStateStepping;
-  return lldb::eStateRunning;
-}
-
-bool
-ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription(
-    StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream,
-    bool &script_error) {
-  StructuredData::Generic *generic = nullptr;
-  if (implementor_sp)
-    generic = implementor_sp->GetAsGeneric();
-  if (!generic) {
-    script_error = true;
-    return false;
-  }
-  Locker py_lock(this,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-  return SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-      generic->GetValue(), "stop_description", stream, script_error);
-}
-
-
 StructuredData::GenericSP
 ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(
     const char *class_name, const StructuredDataImpl &args_data,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index a33499816d8d38c..36737439a7d6ec0 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -77,34 +77,9 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   StructuredData::GenericSP
   CreateScriptCommandObject(const char *class_name) override;
 
-  StructuredData::ObjectSP
-  CreateScriptedThreadPlan(const char *class_name,
-                           const StructuredDataImpl &args_data,
-                           std::string &error_str,
-                           lldb::ThreadPlanSP thread_plan) override;
-
   StructuredData::ObjectSP
   CreateStructuredDataFromScriptObject(ScriptObject obj) override;
 
-  bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
-                                      Event *event,
-                                      bool &script_error) override;
-
-  bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
-                                    Event *event, bool &script_error) override;
-
-  bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
-                                 bool &script_error) override;
-
-  lldb::StateType
-  ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
-                                bool &script_error) override;
-
-  bool
-  ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp,
-                                lldb_private::Stream *s,
-                                bool &script_error) override;
-
   StructuredData::GenericSP
   CreateScriptedBreakpointResolver(const char *class_name,
                                    const StructuredDataImpl &args_data,
@@ -135,6 +110,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
 
   lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
+  
+  lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override;
 
   lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override;
 
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
index d6de6b3c3cf0497..9973d2ea1562fa8 100644
--- a/lldb/source/Target/ThreadPlanPython.cpp
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -32,6 +32,24 @@ ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
                  eVoteNoOpinion, eVoteNoOpinion),
       m_class_name(class_name), m_args_data(args_data), m_did_push(false),
       m_stop_others(false) {
+  ScriptInterpreter* interpreter = GetScriptInterpreter();
+  if (!interpreter) {
+    SetPlanComplete(false);
+    // FIXME: error handling
+    return;
+  }
+
+        
+  m_interface = interpreter->CreateScriptedThreadPlanInterface();
+  if (!m_interface) {
+    SetPlanComplete(false);
+    // FIXME: error handling
+    // error.SetErrorStringWithFormat(
+    //     "ThreadPlanPython::%s () - ERROR: %s", __FUNCTION__,
+    //     "Script interpreter couldn't create Scripted Thread Plan Interface");
+    return;
+  }
+        
   SetIsControllingPlan(true);
   SetOkayToDiscard(true);
   SetPrivate(false);
@@ -60,14 +78,8 @@ void ThreadPlanPython::DidPush() {
   // We set up the script side in DidPush, so that it can push other plans in
   // the constructor, and doesn't have to care about the details of DidPush.
   m_did_push = true;
-  if (!m_class_name.empty()) {
-    ScriptInterpreter *script_interp = GetScriptInterpreter();
-    if (script_interp) {
-      m_implementation_sp = script_interp->CreateScriptedThreadPlan(
-          m_class_name.c_str(), m_args_data, m_error_str, 
-          this->shared_from_this());
-    }
-  }
+  if (m_interface)
+    m_implementation_sp = m_interface->CreatePluginObject(m_class_name, this->shared_from_this(), m_args_data);
 }
 
 bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
@@ -80,10 +92,9 @@ bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
       bool script_error;
-      should_stop = script_interp->ScriptedThreadPlanShouldStop(
-          m_implementation_sp, event_ptr, script_error);
-      if (script_error)
-        SetPlanComplete(false);
+      should_stop = m_interface->ShouldStop(event_ptr);
+//      if (script_error)
+//        SetPlanComplete(false);
     }
   }
   return should_stop;
@@ -99,10 +110,9 @@ bool ThreadPlanPython::IsPlanStale() {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
       bool script_error;
-      is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
-                                                          script_error);
-      if (script_error)
-        SetPlanComplete(false);
+      is_stale = m_interface->IsStale();
+//      if (script_error)
+//        SetPlanComplete(false);
     }
   }
   return is_stale;
@@ -118,10 +128,9 @@ bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
       bool script_error;
-      explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
-          m_implementation_sp, event_ptr, script_error);
-      if (script_error)
-        SetPlanComplete(false);
+      explains_stop = m_interface->ExplainsStop(event_ptr);
+//      if (script_error)
+//        SetPlanComplete(false);
     }
   }
   return explains_stop;
@@ -154,8 +163,7 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
       bool script_error;
-      run_state = script_interp->ScriptedThreadPlanGetRunState(
-          m_implementation_sp, script_error);
+      run_state = m_interface->GetRunState();
     }
   }
   return run_state;
@@ -168,9 +176,8 @@ void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
   if (m_implementation_sp) {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
-      bool script_error;
-      bool added_desc = script_interp->ScriptedThreadPlanGetStopDescription(
-          m_implementation_sp, s, script_error);
+      bool script_error = true;
+      bool added_desc = m_interface->GetStopDescription(s);
       if (script_error || !added_desc)
         s->Printf("Python thread plan implemented by class %s.",
             m_class_name.c_str());
diff --git a/lldb/test/API/functionalities/step_scripted/Steps.py b/lldb/test/API/functionalities/step_scripted/Steps.py
index 7527607be847a56..3325dba75365713 100644
--- a/lldb/test/API/functionalities/step_scripted/Steps.py
+++ b/lldb/test/API/functionalities/step_scripted/Steps.py
@@ -47,7 +47,7 @@ def queue_child_thread_plan(self):
 
 # This plan does a step-over until a variable changes value.
 class StepUntil(StepWithChild):
-    def __init__(self, thread_plan, args_data, dict):
+    def __init__(self, thread_plan, args_data):
         self.thread_plan = thread_plan
         self.frame = thread_plan.GetThread().frames[0]
         self.target = thread_plan.GetThread().GetProcess().GetTarget()
@@ -99,7 +99,7 @@ def stop_description(self, stream):
 class StepReportsStopOthers:
     stop_mode_dict = {}
 
-    def __init__(self, thread_plan, args_data, dict):
+    def __init__(self, thread_plan, args_data):
         self.thread_plan = thread_plan
         self.key = str(args_data.GetValueForKey("token").GetUnsignedIntegerValue(1000))
 
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 14fe69fe70a3fa8..19b794e47c34526 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -96,26 +96,6 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject(
   return python::PythonObject();
 }
 
-python::PythonObject
-lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan(
-    const char *python_class_name, const char *session_dictionary_name,
-    const StructuredDataImpl &args_data, std::string &error_string,
-    const lldb::ThreadPlanSP &thread_plan_sp) {
-  return python::PythonObject();
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-    void *implementor, const char *method_name, Event *event_sp,
-    bool &got_error) {
-  return false;
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
-    void *implementor, const char *method_name, Stream *event_sp,
-    bool &got_error) {
-  return false;
-}
-
 python::PythonObject lldb_private::python::SWIGBridge::
     LLDBSwigPythonCreateScriptedBreakpointResolver(
         const char *python_class_name, const char *session_dictionary_name,

>From 1eae1e01354afeb00262268a2cddb3c55cc89e74 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Fri, 20 Oct 2023 10:20:36 -0700
Subject: [PATCH 7/9] Revert "[lldb][NFCI] Remove use of ConstString in
 StructuredData"

This reverts commit a5a2a5a3eca06998d9f71186db2ce78ae2716022, since it
breaks debugging for `StructuredData::Dictionary` object. This is caused
by the fact `llvm::StringMap` is an opaque type and doesn't have any
data formatter available.

Differential Revision: https://reviews.llvm.org/D159313
---
 lldb/include/lldb/Utility/StructuredData.h    | 33 +++++++++++-----
 .../Platform/MacOSX/PlatformDarwin.cpp        |  4 +-
 .../Process/gdb-remote/ProcessGDBRemote.cpp   | 39 ++++++++++---------
 .../MacOSX/SymbolVendorMacOSX.cpp             |  6 +--
 lldb/source/Target/Target.cpp                 |  5 ++-
 lldb/source/Utility/StructuredData.cpp        | 33 +++-------------
 6 files changed, 58 insertions(+), 62 deletions(-)

diff --git a/lldb/include/lldb/Utility/StructuredData.h b/lldb/include/lldb/Utility/StructuredData.h
index 279238f9af76e01..4133c0e036a22a1 100644
--- a/lldb/include/lldb/Utility/StructuredData.h
+++ b/lldb/include/lldb/Utility/StructuredData.h
@@ -9,10 +9,10 @@
 #ifndef LLDB_UTILITY_STRUCTUREDDATA_H
 #define LLDB_UTILITY_STRUCTUREDDATA_H
 
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
 
+#include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/Stream.h"
 #include "lldb/lldb-enumerations.h"
@@ -423,25 +423,34 @@ class StructuredData {
 
     size_t GetSize() const { return m_dict.size(); }
 
-    void ForEach(std::function<bool(llvm::StringRef key, Object *object)> const
+    void ForEach(std::function<bool(ConstString key, Object *object)> const
                      &callback) const {
       for (const auto &pair : m_dict) {
-        if (!callback(pair.first(), pair.second.get()))
+        if (!callback(pair.first, pair.second.get()))
           break;
       }
     }
 
     ArraySP GetKeys() const {
       auto array_sp = std::make_shared<Array>();
-      for (auto iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
-        auto key_object_sp = std::make_shared<String>(iter->first());
+      collection::const_iterator iter;
+      for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
+        auto key_object_sp = std::make_shared<String>();
+        key_object_sp->SetValue(iter->first.AsCString());
         array_sp->Push(key_object_sp);
       }
       return array_sp;
     }
 
     ObjectSP GetValueForKey(llvm::StringRef key) const {
-      return m_dict.lookup(key);
+      ObjectSP value_sp;
+      if (!key.empty()) {
+        ConstString key_cs(key);
+        collection::const_iterator iter = m_dict.find(key_cs);
+        if (iter != m_dict.end())
+          value_sp = iter->second;
+      }
+      return value_sp;
     }
 
     bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
@@ -530,10 +539,15 @@ class StructuredData {
       return false;
     }
 
-    bool HasKey(llvm::StringRef key) const { return m_dict.contains(key); }
+    bool HasKey(llvm::StringRef key) const {
+      ConstString key_cs(key);
+      collection::const_iterator search = m_dict.find(key_cs);
+      return search != m_dict.end();
+    }
 
     void AddItem(llvm::StringRef key, ObjectSP value_sp) {
-      m_dict.insert_or_assign(key, std::move(value_sp));
+      ConstString key_cs(key);
+      m_dict[key_cs] = std::move(value_sp);
     }
 
     template <typename T> void AddIntegerItem(llvm::StringRef key, T value) {
@@ -563,7 +577,8 @@ class StructuredData {
     void GetDescription(lldb_private::Stream &s) const override;
 
   protected:
-    llvm::StringMap<ObjectSP> m_dict;
+    typedef std::map<ConstString, ObjectSP> collection;
+    collection m_dict;
   };
 
   class Null : public Object {
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 765902c7cf29b87..ed617fe79fb476c 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -989,7 +989,7 @@ PlatformDarwin::ExtractAppSpecificInfo(Process &process) {
   StructuredData::DictionarySP dict_sp =
       std::make_shared<StructuredData::Dictionary>();
 
-  auto flatten_asi_dict = [&dict_sp](llvm::StringRef key,
+  auto flatten_asi_dict = [&dict_sp](ConstString key,
                                      StructuredData::Object *val) -> bool {
     if (!val)
       return false;
@@ -998,7 +998,7 @@ PlatformDarwin::ExtractAppSpecificInfo(Process &process) {
     if (!arr || !arr->GetSize())
       return false;
 
-    dict_sp->AddItem(key, arr->GetItemAtIndex(0));
+    dict_sp->AddItem(key.AsCString(), arr->GetItemAtIndex(0));
     return true;
   };
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 56fc5490657ea71..2a5753a94850f19 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1927,23 +1927,24 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
 
 lldb::ThreadSP
 ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
-  static constexpr llvm::StringLiteral g_key_tid("tid");
-  static constexpr llvm::StringLiteral g_key_name("name");
-  static constexpr llvm::StringLiteral g_key_reason("reason");
-  static constexpr llvm::StringLiteral g_key_metype("metype");
-  static constexpr llvm::StringLiteral g_key_medata("medata");
-  static constexpr llvm::StringLiteral g_key_qaddr("qaddr");
-  static constexpr llvm::StringLiteral g_key_dispatch_queue_t(
-      "dispatch_queue_t");
-  static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue(
+  static ConstString g_key_tid("tid");
+  static ConstString g_key_name("name");
+  static ConstString g_key_reason("reason");
+  static ConstString g_key_metype("metype");
+  static ConstString g_key_medata("medata");
+  static ConstString g_key_qaddr("qaddr");
+  static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
+  static ConstString g_key_associated_with_dispatch_queue(
       "associated_with_dispatch_queue");
-  static constexpr llvm::StringLiteral g_key_queue_name("qname");
-  static constexpr llvm::StringLiteral g_key_queue_kind("qkind");
-  static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum");
-  static constexpr llvm::StringLiteral g_key_registers("registers");
-  static constexpr llvm::StringLiteral g_key_memory("memory");
-  static constexpr llvm::StringLiteral g_key_description("description");
-  static constexpr llvm::StringLiteral g_key_signal("signal");
+  static ConstString g_key_queue_name("qname");
+  static ConstString g_key_queue_kind("qkind");
+  static ConstString g_key_queue_serial_number("qserialnum");
+  static ConstString g_key_registers("registers");
+  static ConstString g_key_memory("memory");
+  static ConstString g_key_address("address");
+  static ConstString g_key_bytes("bytes");
+  static ConstString g_key_description("description");
+  static ConstString g_key_signal("signal");
 
   // Stop with signal and thread info
   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
@@ -1971,7 +1972,7 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
                         &thread_dispatch_qaddr, &queue_vars_valid,
                         &associated_with_dispatch_queue, &dispatch_queue_t,
                         &queue_name, &queue_kind, &queue_serial_number](
-                           llvm::StringRef key,
+                           ConstString key,
                            StructuredData::Object *object) -> bool {
     if (key == g_key_tid) {
       // thread in big endian hex
@@ -2029,10 +2030,10 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
 
       if (registers_dict) {
         registers_dict->ForEach(
-            [&expedited_register_map](llvm::StringRef key,
+            [&expedited_register_map](ConstString key,
                                       StructuredData::Object *object) -> bool {
               uint32_t reg;
-              if (llvm::to_integer(key, reg))
+              if (llvm::to_integer(key.AsCString(), reg))
                 expedited_register_map[reg] =
                     std::string(object->GetStringValue());
               return true; // Keep iterating through all array items
diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index 6008c582454a7ba..7a1568f0b26c1e5 100644
--- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -224,7 +224,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
                           [&module_sp, new_style_source_remapping_dictionary,
                            original_DBGSourcePath_value,
                            do_truncate_remapping_names](
-                              llvm::StringRef key,
+                              ConstString key,
                               StructuredData::Object *object) -> bool {
                             if (object && object->GetAsString()) {
 
@@ -237,7 +237,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
                                 DBGSourcePath = original_DBGSourcePath_value;
                               }
                               module_sp->GetSourceMappingList().Append(
-                                  key, DBGSourcePath, true);
+                                  key.GetStringRef(), DBGSourcePath, true);
                               // With version 2 of DBGSourcePathRemapping, we
                               // can chop off the last two filename parts
                               // from the source remapping and get a more
@@ -245,7 +245,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
                               // Add this as another option in addition to
                               // the full source path remap.
                               if (do_truncate_remapping_names) {
-                                FileSpec build_path(key);
+                                FileSpec build_path(key.AsCString());
                                 FileSpec source_path(DBGSourcePath.c_str());
                                 build_path.RemoveLastPathComponent();
                                 build_path.RemoveLastPathComponent();
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 069b7bcdc40e614..3bbebe08eeeed15 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3899,10 +3899,11 @@ void Target::StopHookScripted::GetSubclassDescription(
   s.Indent("Args:\n");
   s.SetIndentLevel(s.GetIndentLevel() + 4);
 
-  auto print_one_element = [&s](llvm::StringRef key,
+  auto print_one_element = [&s](ConstString key,
                                 StructuredData::Object *object) {
     s.Indent();
-    s.Format("{0} : {1}\n", key, object->GetStringValue());
+    s.Printf("%s : %s\n", key.GetCString(),
+              object->GetStringValue().str().c_str());
     return true;
   };
 
diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp
index 7686d052c599c67..c870a0eb82b27c4 100644
--- a/lldb/source/Utility/StructuredData.cpp
+++ b/lldb/source/Utility/StructuredData.cpp
@@ -162,18 +162,8 @@ void StructuredData::String::Serialize(json::OStream &s) const {
 
 void StructuredData::Dictionary::Serialize(json::OStream &s) const {
   s.objectBegin();
-
-  // To ensure the output format is always stable, we sort the dictionary by key
-  // first.
-  using Entry = std::pair<llvm::StringRef, ObjectSP>;
-  std::vector<Entry> sorted_entries;
-  for (const auto &pair : m_dict)
-    sorted_entries.push_back({pair.first(), pair.second});
-
-  llvm::sort(sorted_entries);
-
-  for (const auto &pair : sorted_entries) {
-    s.attributeBegin(pair.first);
+  for (const auto &pair : m_dict) {
+    s.attributeBegin(pair.first.GetStringRef());
     pair.second->Serialize(s);
     s.attributeEnd();
   }
@@ -238,20 +228,9 @@ void StructuredData::Array::GetDescription(lldb_private::Stream &s) const {
 
 void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
   size_t indentation_level = s.GetIndentLevel();
-
-  // To ensure the output format is always stable, we sort the dictionary by key
-  // first.
-  using Entry = std::pair<llvm::StringRef, ObjectSP>;
-  std::vector<Entry> sorted_entries;
-  for (const auto &pair : m_dict)
-    sorted_entries.push_back({pair.first(), pair.second});
-
-  llvm::sort(sorted_entries);
-
-  for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
-       iter++) {
+  for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) {
     // Sanitize.
-    if (iter->first.empty() || !iter->second)
+    if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second)
       continue;
 
     // Reset original indentation level.
@@ -259,7 +238,7 @@ void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
     s.Indent();
 
     // Print key.
-    s.Format("{0}:", iter->first);
+    s.Printf("%s:", iter->first.AsCString());
 
     // Return to new line and increase indentation if value is record type.
     // Otherwise add spacing.
@@ -273,7 +252,7 @@ void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
 
     // Print value and new line if now last pair.
     iter->second->GetDescription(s);
-    if (std::next(iter) != sorted_entries.end())
+    if (std::next(iter) != m_dict.end())
       s.EOL();
 
     // Reset indentation level if it was incremented previously.

>From aa0c2ed926a20aea93f3134c11235741a7d931cd Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Fri, 20 Oct 2023 18:31:58 -0700
Subject: [PATCH 8/9] [lldb] Fix Stream bijection for ScriptedPythonInterface

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/python-swigsafecast.swig      |  8 ++++----
 lldb/bindings/python/python-wrapper.swig           | 14 +++++++++++++-
 lldb/include/lldb/API/SBStream.h                   |  9 +++++++++
 lldb/include/lldb/Interpreter/ScriptInterpreter.h  |  3 +++
 lldb/source/Interpreter/ScriptInterpreter.cpp      |  8 ++++++++
 .../Python/Interfaces/ScriptedPythonInterface.cpp  | 13 +++++++++++++
 .../Python/Interfaces/ScriptedPythonInterface.h    |  8 ++++++++
 .../ScriptedThreadPlanPythonInterface.cpp          |  2 +-
 .../ScriptInterpreter/Python/SWIGPythonBridge.h    |  3 ++-
 .../ScriptInterpreter/Python/PythonTestSuite.cpp   |  5 +++++
 10 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig
index d5ea5148727134d..362842df0bb8c6a 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -37,10 +37,6 @@ PythonObject SWIGBridge::ToSWIGWrapper(const Status& status) {
   return ToSWIGHelper(new lldb::SBError(status), SWIGTYPE_p_lldb__SBError);
 }
 
-PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb) {
-  return ToSWIGHelper(stream_sb.release(), SWIGTYPE_p_lldb__SBStream);
-}
-
 PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb) {
   return ToSWIGHelper(data_sb.release(), SWIGTYPE_p_lldb__SBStructuredData);
 }
@@ -120,6 +116,10 @@ ScopedPythonObject<lldb::SBEvent> SWIGBridge::ToSWIGWrapper(Event *event) {
                                            SWIGTYPE_p_lldb__SBEvent);
 }
 
+PythonObject SWIGBridge::ToSWIGWrapper(const Stream *s) {
+  return ToSWIGHelper(new lldb::SBStream(), SWIGTYPE_p_lldb__SBStream);
+}
+
 PythonObject SWIGBridge::ToSWIGWrapper(
     std::unique_ptr<lldb::SBFileSpec> file_spec_sb) {
   return ToSWIGHelper(file_spec_sb.release(), SWIGTYPE_p_lldb__SBFileSpec);
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index a1e2febaf209c25..84622d6c2ae4e38 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -427,7 +427,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
 
   auto *sb_stream = new lldb::SBStream();
   PythonObject sb_stream_arg =
-      SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream>(sb_stream));
+      SWIGBridge::ToSWIGWrapper(stream.get());
   PythonObject result =
       pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg);
 
@@ -678,6 +678,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data
   return sb_ptr;
 }
 
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * data) {
+  lldb::SBStream *sb_ptr = nullptr;
+
+  int valid_cast =
+      SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBStream, 0);
+
+  if (valid_cast == -1)
+    return NULL;
+
+  return sb_ptr;
+}
+
 void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) {
   lldb::SBValue *sb_ptr = NULL;
 
diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h
index 0e33f05b69916f2..ee329737d594b5f 100644
--- a/lldb/include/lldb/API/SBStream.h
+++ b/lldb/include/lldb/API/SBStream.h
@@ -13,6 +13,13 @@
 
 #include "lldb/API/SBDefines.h"
 
+namespace lldb_private {
+class ScriptInterpreter;
+namespace python {
+class SWIGBridge;
+}
+} // namespace lldb_private
+
 namespace lldb {
 
 class LLDB_API SBStream {
@@ -101,6 +108,8 @@ class LLDB_API SBStream {
   friend class SBValue;
   friend class SBWatchpoint;
 
+  friend class lldb_private::ScriptInterpreter;
+
   lldb_private::Stream *operator->();
 
   lldb_private::Stream *get();
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 73827bd0f2953c5..8f57d2318e6db4c 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -15,6 +15,7 @@
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBLaunchInfo.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
+#include "lldb/API/SBStream.h"
 #include "lldb/Breakpoint/BreakpointOptions.h"
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Core/SearchFilter.h"
@@ -567,6 +568,8 @@ class ScriptInterpreter : public PluginInterface {
 
   Status GetStatusFromSBError(const lldb::SBError &error) const;
 
+  Stream *GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const;
+
   lldb::BreakpointSP
   GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;
 
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index fb3fa74d0b97804..e171b2dd42d35af 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -104,6 +104,14 @@ ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {
   return Status();
 }
 
+Stream *ScriptInterpreter::GetOpaqueTypeFromSBStream(
+    const lldb::SBStream &stream) const {
+  if (stream.m_opaque_up)
+    return const_cast<lldb::SBStream &>(stream).m_opaque_up.release();
+
+  return nullptr;
+}
+
 std::optional<MemoryRegionInfo>
 ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
     const lldb::SBMemoryRegionInfo &mem_region) const {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 6f22503b279ca62..9574ed147c1e684 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -54,6 +54,19 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
   return {};
 }
 
+template <>
+Stream *ScriptedPythonInterface::ExtractValueFromPythonObject<Stream *>(
+    python::PythonObject &p, Status &error) {
+  if (lldb::SBStream *sb_stream = reinterpret_cast<lldb::SBStream *>(
+          python::LLDBSWIGPython_CastPyObjectToSBStream(p.get())))
+    return m_interpreter.GetOpaqueTypeFromSBStream(*sb_stream);
+  else
+    error.SetErrorString(
+        "Couldn't cast lldb::SBStream to lldb_private::Stream.");
+
+  return nullptr;
+}
+
 template <>
 lldb::DataExtractorSP
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index efd34496846b72b..de3635aa6257430 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -218,6 +218,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
 
+  python::PythonObject Transform(Stream *arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+
   python::PythonObject Transform(lldb::DataExtractorSP arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
@@ -315,6 +319,10 @@ template <>
 Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
     python::PythonObject &p, Status &error);
 
+template <>
+Stream *ScriptedPythonInterface::ExtractValueFromPythonObject<Stream *>(
+    python::PythonObject &p, Status &error);
+
 template <>
 lldb::BreakpointSP
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>(
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
index 3f5f626e4b9e7b3..8ce7d332b8b1618 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
@@ -78,7 +78,7 @@ lldb::StateType ScriptedThreadPlanPythonInterface::GetRunState() {
 
 bool ScriptedThreadPlanPythonInterface::GetStopDescription(lldb_private::Stream *s) {
   Status error;
-  StructuredData::ObjectSP obj = Dispatch("stop_description", error);
+  StructuredData::ObjectSP obj = Dispatch("stop_description", error, s);
 
   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
     return false;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 032df4f37a4081d..dbd44c6421c20ca 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -96,12 +96,12 @@ class SWIGBridge {
   static PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp);
   static PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options);
   static PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx);
+  static PythonObject ToSWIGWrapper(const Stream *stream);
 
   static PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp);
   static PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp);
   static PythonObject ToSWIGWrapper(lldb::DataExtractorSP data_extractor_sp);
 
-  static PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb);
   static PythonObject
   ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb);
   static PythonObject
@@ -253,6 +253,7 @@ void *LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data);
+void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
 } // namespace python
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 19b794e47c34526..9992cf6d5ed9ec9 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -301,3 +301,8 @@ python::PythonObject
 lldb_private::python::SWIGBridge::ToSWIGWrapper(lldb::DataExtractorSP) {
   return python::PythonObject();
 }
+
+python::PythonObject
+lldb_private::python::SWIGBridge::ToSWIGWrapper(const Stream *stream) {
+  return python::PythonObject();
+}

>From 286164fc03f1436d322dd2bb0a985e5f2335e44a Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Sat, 21 Oct 2023 02:52:19 -0700
Subject: [PATCH 9/9] [lldb/test] Fix TestStepScripted.py

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/bindings/python/python-swigsafecast.swig |  9 ++-
 lldb/bindings/python/python-wrapper.swig      | 12 ++++
 lldb/include/lldb/API/SBEvent.h               |  4 +-
 .../Interfaces/ScriptedProcessInterface.h     |  6 +-
 .../Interfaces/ScriptedThreadInterface.h      |  6 +-
 .../Interfaces/ScriptedThreadPlanInterface.h  | 18 ++---
 .../lldb/Interpreter/ScriptInterpreter.h      |  3 +
 lldb/source/Interpreter/ScriptInterpreter.cpp |  5 ++
 .../Python/OperatingSystemPython.cpp          | 12 ++--
 .../Process/scripted/ScriptedProcess.cpp      | 11 +++-
 .../Process/scripted/ScriptedThread.cpp       | 13 ++--
 .../OperatingSystemPythonInterface.cpp        |  8 +--
 .../OperatingSystemPythonInterface.h          |  4 +-
 .../ScriptedProcessPythonInterface.cpp        |  4 +-
 .../ScriptedProcessPythonInterface.h          | 10 +--
 .../Interfaces/ScriptedPythonInterface.cpp    | 21 ++++++
 .../Interfaces/ScriptedPythonInterface.h      | 53 ++++++++-------
 .../ScriptedThreadPlanPythonInterface.cpp     | 39 +++++------
 .../ScriptedThreadPlanPythonInterface.h       | 17 +++--
 .../ScriptedThreadPythonInterface.cpp         |  3 +-
 .../ScriptedThreadPythonInterface.h           |  4 +-
 .../Python/SWIGPythonBridge.h                 |  3 +-
 lldb/source/Target/ThreadPlanPython.cpp       | 66 +++++++++----------
 .../Python/PythonTestSuite.cpp                | 15 +++++
 24 files changed, 214 insertions(+), 132 deletions(-)

diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig
index 362842df0bb8c6a..fba3a77d8f2df44 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -111,15 +111,14 @@ SWIGBridge::ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
       SWIGTYPE_p_lldb__SBCommandReturnObject);
 }
 
-ScopedPythonObject<lldb::SBEvent> SWIGBridge::ToSWIGWrapper(Event *event) {
-  return ScopedPythonObject<lldb::SBEvent>(new lldb::SBEvent(event),
-                                           SWIGTYPE_p_lldb__SBEvent);
-}
-
 PythonObject SWIGBridge::ToSWIGWrapper(const Stream *s) {
   return ToSWIGHelper(new lldb::SBStream(), SWIGTYPE_p_lldb__SBStream);
 }
 
+PythonObject SWIGBridge::ToSWIGWrapper(Event *event) {
+  return ToSWIGHelper(new lldb::SBEvent(event), SWIGTYPE_p_lldb__SBEvent);
+}
+
 PythonObject SWIGBridge::ToSWIGWrapper(
     std::unique_ptr<lldb::SBFileSpec> file_spec_sb) {
   return ToSWIGHelper(file_spec_sb.release(), SWIGTYPE_p_lldb__SBFileSpec);
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 84622d6c2ae4e38..60bb16983238594 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -678,6 +678,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data
   return sb_ptr;
 }
 
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBEvent(PyObject * data) {
+  lldb::SBEvent *sb_ptr = nullptr;
+
+  int valid_cast =
+      SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBEvent, 0);
+
+  if (valid_cast == -1)
+    return NULL;
+
+  return sb_ptr;
+}
+
 void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * data) {
   lldb::SBStream *sb_ptr = nullptr;
 
diff --git a/lldb/include/lldb/API/SBEvent.h b/lldb/include/lldb/API/SBEvent.h
index cc116766e85f4ad..85b401ca8cc100f 100644
--- a/lldb/include/lldb/API/SBEvent.h
+++ b/lldb/include/lldb/API/SBEvent.h
@@ -15,6 +15,7 @@
 #include <vector>
 
 namespace lldb_private {
+class ScriptInterpreter;
 namespace python {
 class SWIGBridge;
 }
@@ -73,11 +74,12 @@ class LLDB_API SBEvent {
   friend class SBThread;
   friend class SBWatchpoint;
 
+  friend class lldb_private::ScriptInterpreter;
   friend class lldb_private::python::SWIGBridge;
 
   SBEvent(lldb::EventSP &event_sp);
 
-  SBEvent(lldb_private::Event *event_sp);
+  SBEvent(lldb_private::Event *event);
 
   lldb::EventSP &GetSP() const;
 
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
index 5a030f29907ffb6..cbbfa83f70ff68f 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedProcessInterface.h
@@ -21,13 +21,13 @@
 namespace lldb_private {
 class ScriptedProcessInterface : virtual public ScriptedInterface {
 public:
-  virtual StructuredData::GenericSP
+  virtual llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
                      StructuredData::Generic *script_obj = nullptr) {
-    return {};
+    llvm_unreachable("unimplemented!");
   }
-  
+
   virtual StructuredData::DictionarySP GetCapabilities() { return {}; }
 
   virtual Status Attach(const ProcessAttachInfo &attach_info) {
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
index 3cb3d7b231c68e3..7568c2a3443b3d5 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
@@ -20,13 +20,13 @@
 namespace lldb_private {
 class ScriptedThreadInterface : public ScriptedInterface {
 public:
-  virtual StructuredData::GenericSP
+  virtual llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
                      StructuredData::Generic *script_obj = nullptr) {
-    return {};
+    llvm_unreachable("unimplemented!");
   }
-  
+
   virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; }
 
   virtual std::optional<std::string> GetName() { return std::nullopt; }
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
index 972254e1fd4d89f..2fe769cfe7b140b 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
@@ -16,22 +16,24 @@
 namespace lldb_private {
 class ScriptedThreadPlanInterface : public ScriptedInterface {
 public:
-  virtual StructuredData::GenericSP
+  virtual llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name,
                      lldb::ThreadPlanSP thread_plan_sp,
-                     const StructuredDataImpl& args_sp) {
-    return {};
+                     const StructuredDataImpl &args_sp) {
+    llvm_unreachable("unimplemented!");
   }
-  
-  virtual bool ExplainsStop(Event *event) { return true; }
 
-  virtual bool ShouldStop(Event *event) { return true; }
+  virtual llvm::Expected<bool> ExplainsStop(Event *event) { return true; }
 
-  virtual bool IsStale() { return true; };
+  virtual llvm::Expected<bool> ShouldStop(Event *event) { return true; }
+
+  virtual llvm::Expected<bool> IsStale() { return true; };
 
   virtual lldb::StateType GetRunState() { return lldb::eStateStepping; }
 
-  virtual bool GetStopDescription(lldb_private::Stream *s) { return true; }
+  virtual llvm::Expected<bool> GetStopDescription(lldb_private::Stream *s) {
+    return true;
+  }
 };
 } // namespace lldb_private
 
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 8f57d2318e6db4c..ffa7a2ad818e5c1 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -13,6 +13,7 @@
 #include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBData.h"
 #include "lldb/API/SBError.h"
+#include "lldb/API/SBEvent.h"
 #include "lldb/API/SBLaunchInfo.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
 #include "lldb/API/SBStream.h"
@@ -568,6 +569,8 @@ class ScriptInterpreter : public PluginInterface {
 
   Status GetStatusFromSBError(const lldb::SBError &error) const;
 
+  Event *GetOpaqueTypeFromSBEvent(const lldb::SBEvent &event) const;
+
   Stream *GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const;
 
   lldb::BreakpointSP
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index e171b2dd42d35af..6aeed7694404779 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -104,6 +104,11 @@ ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {
   return Status();
 }
 
+Event *
+ScriptInterpreter::GetOpaqueTypeFromSBEvent(const lldb::SBEvent &event) const {
+  return event.get();
+}
+
 Stream *ScriptInterpreter::GetOpaqueTypeFromSBStream(
     const lldb::SBStream &stream) const {
   if (stream.m_opaque_up)
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 96861b2a20dc869..ac6cac5cf19fa06 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -115,13 +115,15 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
     return;
 
   ExecutionContext exe_ctx(process);
-  StructuredData::GenericSP owned_script_object_sp =
-      operating_system_interface->CreatePluginObject(os_plugin_class_name, exe_ctx, nullptr);
+  auto obj_or_err = operating_system_interface->CreatePluginObject(
+      os_plugin_class_name, exe_ctx, nullptr);
 
-  if (!owned_script_object_sp)
-    //    return llvm::createStringError(llvm::inconvertibleErrorCode(),
-    //                                   "Failed to create script object.");
+  if (!obj_or_err) {
+    llvm::consumeError(obj_or_err.takeError());
     return;
+  }
+
+  StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
   if (!owned_script_object_sp->IsValid())
     //    return llvm::createStringError(llvm::inconvertibleErrorCode(),
     //                                   "Created script object is invalid.");
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index 0990506f1117fb6..e0e6693399dec3a 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -108,7 +108,16 @@ ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
   ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
 
   // Create process script object
-  StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(m_scripted_metadata.GetClassName(), exe_ctx, m_scripted_metadata.GetArgsSP());
+  auto obj_or_err = GetInterface().CreatePluginObject(
+      m_scripted_metadata.GetClassName(), exe_ctx,
+      m_scripted_metadata.GetArgsSP());
+
+  if (!obj_or_err) {
+    error.SetErrorString("Failed to create script object.");
+    return;
+  }
+
+  StructuredData::GenericSP object_sp = *obj_or_err;
 
   if (!object_sp || !object_sp->IsValid()) {
     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index 105446ae55a0b60..362a6e2674b19f9 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -56,14 +56,17 @@ ScriptedThread::Create(ScriptedProcess &process,
   }
 
   ExecutionContext exe_ctx(process);
-  StructuredData::GenericSP owned_script_object_sp =
-      scripted_thread_interface->CreatePluginObject(
-          thread_class_name,
-          exe_ctx, process.m_scripted_metadata.GetArgsSP(), script_object);
+  auto obj_or_err = scripted_thread_interface->CreatePluginObject(
+      thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(),
+      script_object);
 
-  if (!owned_script_object_sp)
+  if (!obj_or_err) {
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                    "Failed to create script object.");
+  }
+
+  StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
+
   if (!owned_script_object_sp->IsValid())
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                    "Created script object is invalid.");
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
index 0defa0ec00eba46..c45a35166a55732 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp
@@ -29,10 +29,10 @@ OperatingSystemPythonInterface::OperatingSystemPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {}
 
-StructuredData::GenericSP
-OperatingSystemPythonInterface::CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
-                                                   StructuredData::DictionarySP args_sp,
-                                                   StructuredData::Generic *script_obj) {
+llvm::Expected<StructuredData::GenericSP>
+OperatingSystemPythonInterface::CreatePluginObject(
+    llvm::StringRef class_name, ExecutionContext &exe_ctx,
+    StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
   return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, exe_ctx.GetProcessSP());
 }
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
index 323cebf5b919eff..ee24e0ee30f91b3 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h
@@ -23,8 +23,8 @@ class OperatingSystemPythonInterface
       virtual public ScriptedThreadPythonInterface {
 public:
   OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-        
-  StructuredData::GenericSP
+
+  llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
                      StructuredData::Generic *script_obj = nullptr) override;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
index a251df5d51ce108..1462981fcf36c58 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp
@@ -32,7 +32,9 @@ using Locker = ScriptInterpreterPythonImpl::Locker;
 ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
-StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
+
+llvm::Expected<StructuredData::GenericSP>
+ScriptedProcessPythonInterface::CreatePluginObject(
     llvm::StringRef class_name, ExecutionContext &exe_ctx,
     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
   ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
index 6dda8c812e94281..f3cff619f6624f0 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h
@@ -22,12 +22,12 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
                                        public ScriptedPythonInterface {
 public:
   ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-                                         
-  StructuredData::GenericSP
+
+  llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(const llvm::StringRef class_name,
-                    ExecutionContext &exe_ctx,
-                    StructuredData::DictionarySP args_sp,
-                    StructuredData::Generic *script_obj = nullptr) override;
+                     ExecutionContext &exe_ctx,
+                     StructuredData::DictionarySP args_sp,
+                     StructuredData::Generic *script_obj = nullptr) override;
 
   StructuredData::DictionarySP GetCapabilities() override;
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 9574ed147c1e684..32a5b4af19ca0df 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -26,6 +26,15 @@ ScriptedPythonInterface::ScriptedPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedInterface(), m_interpreter(interpreter) {}
 
+template <>
+void ScriptedPythonInterface::ReverseTransform(
+    lldb_private::Stream *&original_arg, python::PythonObject transformed_arg,
+    Status &error) {
+  Stream *s = ExtractValueFromPythonObject<Stream *>(transformed_arg, error);
+  *original_arg = *s;
+  original_arg->PutCString(static_cast<StreamString *>(s)->GetData());
+}
+
 template <>
 StructuredData::ArraySP
 ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
@@ -54,6 +63,18 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
   return {};
 }
 
+template <>
+Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
+    python::PythonObject &p, Status &error) {
+  if (lldb::SBEvent *sb_event = reinterpret_cast<lldb::SBEvent *>(
+          python::LLDBSWIGPython_CastPyObjectToSBEvent(p.get())))
+    return m_interpreter.GetOpaqueTypeFromSBEvent(*sb_event);
+  else
+    error.SetErrorString("Couldn't cast lldb::SBEvent to lldb_private::Event.");
+
+  return nullptr;
+}
+
 template <>
 Stream *ScriptedPythonInterface::ExtractValueFromPythonObject<Stream *>(
     python::PythonObject &p, Status &error) {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index de3635aa6257430..559a1af652916ed 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -31,17 +31,20 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
 public:
   ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter);
   ~ScriptedPythonInterface() override = default;
-  
-  template <typename ...Args>
-  StructuredData::GenericSP
+
+  template <typename... Args>
+  llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name,
-                     StructuredData::Generic *script_obj, Args ...args) {
+                     StructuredData::Generic *script_obj, Args... args) {
     using namespace python;
     using Locker = ScriptInterpreterPythonImpl::Locker;
     
     std::string error_string;
     if (class_name.empty() && llvm::StringRef(m_interpreter.GetDictionaryName()).empty() && !script_obj)
-      return {};
+      return llvm::createStringError(
+          llvm::inconvertibleErrorCode(),
+          "ScriptedPythonInterface::CreatePluginObject - missing script class "
+          "name, dictionary or object.");
 
     Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
                    Locker::FreeLock);
@@ -53,9 +56,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
       auto pfunc = PythonObject::ResolveNameWithDictionary<python::PythonCallable>(class_name, dict);
 
       if (!pfunc.IsAllocated()) {
-        error_string.append("could not find script class: ");
+        error_string.append("Could not find script class: ");
         error_string.append(class_name);
-        return {};
+        return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                       error_string);
       }
       
       std::tuple<Args...> original_args = std::forward_as_tuple(args...);
@@ -69,36 +73,31 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
             [&](const llvm::ErrorInfoBase &E) {
               error_string.append(E.message());
             });
-        return {};
+        return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                       error_string);
       }
       
       llvm::Expected<PythonObject> expected_return_object =
           llvm::make_error<llvm::StringError>("Not initialized.",
                                               llvm::inconvertibleErrorCode());
-      
+
       std::apply(
           [&pfunc, &expected_return_object](auto &&...args) {
             llvm::consumeError(expected_return_object.takeError());
             expected_return_object = pfunc(args...);
           },
           transformed_args);
-      
-      if (llvm::Error e = expected_return_object.takeError()) {
-        error_string.append(llvm::toString(std::move(e)));
-        return {};
-  //      return ErrorWithMessage<T>(caller_signature,
-  //                                 "Python method could not be called.", error);
-      }
 
+      if (llvm::Error e = expected_return_object.takeError())
+        return e;
       result = std::move(expected_return_object.get());
-      
     } else
       result = PythonObject(PyRefType::Borrowed,
                              static_cast<PyObject *>(script_obj->GetValue()));
-      
-    
+
     if (!result.IsValid())
-      return {};
+      return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                     "python object result is invalid.");
 
     m_object_instance_sp = StructuredData::GenericSP(new StructuredPythonObject(std::move(result)));
     return m_object_instance_sp;
@@ -155,10 +154,6 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
 
     PythonObject py_return = std::move(expected_return_object.get());
 
-    if (!py_return.IsAllocated())
-      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
-                                 error);
-
     // Now that we called the python method with the transformed arguments,
     // we need to interate again over both the original and transformed
     // parameter pack, and transform back the parameter that were passed in
@@ -169,6 +164,8 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
             caller_signature,
             "Couldn't re-assign reference and pointer arguments.", error);
 
+    if (!py_return.IsAllocated())
+      return {};
     return ExtractValueFromPythonObject<T>(py_return, error);
   }
 
@@ -218,6 +215,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
 
+  python::PythonObject Transform(Event *arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+
   python::PythonObject Transform(Stream *arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
@@ -319,6 +320,10 @@ template <>
 Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
     python::PythonObject &p, Status &error);
 
+template <>
+Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
+    python::PythonObject &p, Status &error);
+
 template <>
 Stream *ScriptedPythonInterface::ExtractValueFromPythonObject<Stream *>(
     python::PythonObject &p, Status &error);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
index 8ce7d332b8b1618..4b1001a57721a90 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
@@ -27,41 +27,41 @@ ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {}
 
-
-StructuredData::GenericSP ScriptedThreadPlanPythonInterface::CreatePluginObject(
-                                                                            const llvm::StringRef class_name,
-                                                                                               lldb::ThreadPlanSP thread_plan_sp,
-                                                                                const StructuredDataImpl& args_sp) {
-  // FIXME: Not working
+llvm::Expected<StructuredData::GenericSP>
+ScriptedThreadPlanPythonInterface::CreatePluginObject(
+    const llvm::StringRef class_name, lldb::ThreadPlanSP thread_plan_sp,
+    const StructuredDataImpl &args_sp) {
   return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, thread_plan_sp, args_sp);
 }
 
-bool ScriptedThreadPlanPythonInterface::ExplainsStop(Event *event) {
+llvm::Expected<bool>
+ScriptedThreadPlanPythonInterface::ExplainsStop(Event *event) {
   Status error;
-  StructuredData::ObjectSP obj = Dispatch("explains_stop", error);
+  StructuredData::ObjectSP obj = Dispatch("explains_stop", error, event);
 
   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
-    return false;
+    return error.ToError();
 
   return obj->GetBooleanValue();
 }
 
-bool ScriptedThreadPlanPythonInterface::ShouldStop(Event *event) {
+llvm::Expected<bool>
+ScriptedThreadPlanPythonInterface::ShouldStop(Event *event) {
   Status error;
-  StructuredData::ObjectSP obj = Dispatch("should_stop", error);
+  StructuredData::ObjectSP obj = Dispatch("should_stop", error, event);
 
   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
-    return false;
+    return error.ToError();
 
   return obj->GetBooleanValue();
 }
 
-bool ScriptedThreadPlanPythonInterface::IsStale() {
+llvm::Expected<bool> ScriptedThreadPlanPythonInterface::IsStale() {
   Status error;
   StructuredData::ObjectSP obj = Dispatch("is_stale", error);
 
   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
-    return false;
+    return error.ToError();
 
   return obj->GetBooleanValue();
 }
@@ -76,14 +76,15 @@ lldb::StateType ScriptedThreadPlanPythonInterface::GetRunState() {
   return static_cast<lldb::StateType>(obj->GetUnsignedIntegerValue(static_cast<uint32_t>(lldb::eStateStepping)));
 }
 
-bool ScriptedThreadPlanPythonInterface::GetStopDescription(lldb_private::Stream *s) {
+llvm::Expected<bool>
+ScriptedThreadPlanPythonInterface::GetStopDescription(lldb_private::Stream *s) {
   Status error;
-  StructuredData::ObjectSP obj = Dispatch("stop_description", error, s);
+  Dispatch("stop_description", error, s);
 
-  if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
-    return false;
+  if (error.Fail())
+    return error.ToError();
 
-  return obj->GetBooleanValue();
+  return true;
 }
 
 #endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
index 9ec6f36bc4b1797..2eb986e0282f0f3 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
@@ -22,22 +22,21 @@ class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface,
                                           public ScriptedPythonInterface {
 public:
   ScriptedThreadPlanPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-                                      
-  StructuredData::GenericSP
+
+  llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(const llvm::StringRef class_name,
                      lldb::ThreadPlanSP thread_plan_sp,
-                     const StructuredDataImpl& args_sp) override;
-                                        
-  bool ExplainsStop(Event *event) override;
+                     const StructuredDataImpl &args_sp) override;
 
-  bool ShouldStop(Event *event) override;
+  llvm::Expected<bool> ExplainsStop(Event *event) override;
 
-  bool IsStale() override;
+  llvm::Expected<bool> ShouldStop(Event *event) override;
 
-  lldb::StateType GetRunState() override;
+  llvm::Expected<bool> IsStale() override;
 
-  bool GetStopDescription(lldb_private::Stream *s) override;
+  lldb::StateType GetRunState() override;
 
+  llvm::Expected<bool> GetStopDescription(lldb_private::Stream *s) override;
 };
 } // namespace lldb_private
 
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
index 63a32512e47feda..185caa9d7591fd4 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp
@@ -30,7 +30,8 @@ ScriptedThreadPythonInterface::ScriptedThreadPythonInterface(
     ScriptInterpreterPythonImpl &interpreter)
     : ScriptedThreadInterface(), ScriptedPythonInterface(interpreter) {}
 
-StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject(
+llvm::Expected<StructuredData::GenericSP>
+ScriptedThreadPythonInterface::CreatePluginObject(
     const llvm::StringRef class_name, ExecutionContext &exe_ctx,
     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
   ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
index d7b60d4beff9b5d..b7b7439461a03d6 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h
@@ -22,8 +22,8 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface,
                                       public ScriptedPythonInterface {
 public:
   ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter);
-                                      
-  StructuredData::GenericSP
+
+  llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
                      StructuredData::DictionarySP args_sp,
                      StructuredData::Generic *script_obj = nullptr) override;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index dbd44c6421c20ca..b27ba8236b857b8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -97,6 +97,7 @@ class SWIGBridge {
   static PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options);
   static PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx);
   static PythonObject ToSWIGWrapper(const Stream *stream);
+  static PythonObject ToSWIGWrapper(Event *arg);
 
   static PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp);
   static PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp);
@@ -111,7 +112,6 @@ class SWIGBridge {
 
   static python::ScopedPythonObject<lldb::SBCommandReturnObject>
   ToSWIGWrapper(CommandReturnObject &cmd_retobj);
-  static python::ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event);
   // These prototypes are the Pythonic implementations of the required
   // callbacks. Although these are scripting-language specific, their definition
   // depends on the public API.
@@ -253,6 +253,7 @@ void *LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data);
+void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
index 9973d2ea1562fa8..4629c8ffec7b1c1 100644
--- a/lldb/source/Target/ThreadPlanPython.cpp
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -78,8 +78,15 @@ void ThreadPlanPython::DidPush() {
   // We set up the script side in DidPush, so that it can push other plans in
   // the constructor, and doesn't have to care about the details of DidPush.
   m_did_push = true;
-  if (m_interface)
-    m_implementation_sp = m_interface->CreatePluginObject(m_class_name, this->shared_from_this(), m_args_data);
+  if (m_interface) {
+    auto obj_or_err = m_interface->CreatePluginObject(
+        m_class_name, this->shared_from_this(), m_args_data);
+    if (!obj_or_err) {
+      m_error_str = llvm::toString(obj_or_err.takeError());
+      SetPlanComplete(false);
+    } else
+      m_implementation_sp = *obj_or_err;
+  }
 }
 
 bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
@@ -89,13 +96,12 @@ bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
 
   bool should_stop = true;
   if (m_implementation_sp) {
-    ScriptInterpreter *script_interp = GetScriptInterpreter();
-    if (script_interp) {
-      bool script_error;
-      should_stop = m_interface->ShouldStop(event_ptr);
-//      if (script_error)
-//        SetPlanComplete(false);
-    }
+    auto should_stop_or_err = m_interface->ShouldStop(event_ptr);
+    if (!should_stop_or_err) {
+      llvm::consumeError(should_stop_or_err.takeError());
+      SetPlanComplete(false);
+    } else
+      should_stop = *should_stop_or_err;
   }
   return should_stop;
 }
@@ -107,13 +113,12 @@ bool ThreadPlanPython::IsPlanStale() {
 
   bool is_stale = true;
   if (m_implementation_sp) {
-    ScriptInterpreter *script_interp = GetScriptInterpreter();
-    if (script_interp) {
-      bool script_error;
-      is_stale = m_interface->IsStale();
-//      if (script_error)
-//        SetPlanComplete(false);
-    }
+    auto is_stale_or_err = m_interface->IsStale();
+    if (!is_stale_or_err) {
+      llvm::consumeError(is_stale_or_err.takeError());
+      SetPlanComplete(false);
+    } else
+      is_stale = *is_stale_or_err;
   }
   return is_stale;
 }
@@ -125,13 +130,12 @@ bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
 
   bool explains_stop = true;
   if (m_implementation_sp) {
-    ScriptInterpreter *script_interp = GetScriptInterpreter();
-    if (script_interp) {
-      bool script_error;
-      explains_stop = m_interface->ExplainsStop(event_ptr);
-//      if (script_error)
-//        SetPlanComplete(false);
-    }
+    auto explains_stop_or_error = m_interface->ExplainsStop(event_ptr);
+    if (!explains_stop_or_error) {
+      llvm::consumeError(explains_stop_or_error.takeError());
+      SetPlanComplete(false);
+    } else
+      explains_stop = *explains_stop_or_error;
   }
   return explains_stop;
 }
@@ -159,13 +163,8 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
   LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
             m_class_name.c_str());
   lldb::StateType run_state = eStateRunning;
-  if (m_implementation_sp) {
-    ScriptInterpreter *script_interp = GetScriptInterpreter();
-    if (script_interp) {
-      bool script_error;
-      run_state = m_interface->GetRunState();
-    }
-  }
+  if (m_implementation_sp)
+    run_state = m_interface->GetRunState();
   return run_state;
 }
 
@@ -176,11 +175,12 @@ void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
   if (m_implementation_sp) {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
-      bool script_error = true;
-      bool added_desc = m_interface->GetStopDescription(s);
-      if (script_error || !added_desc)
+      auto desc_or_err = m_interface->GetStopDescription(s);
+      if (!desc_or_err || !*desc_or_err) {
+        llvm::consumeError(desc_or_err.takeError());
         s->Printf("Python thread plan implemented by class %s.",
             m_class_name.c_str());
+      }
     }
     return;
   }
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 9992cf6d5ed9ec9..aefaa16c0fae3fb 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -150,6 +150,16 @@ lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject *data) {
   return nullptr;
 }
 
+void *
+lldb_private::python::LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data) {
+  return nullptr;
+}
+
+void *
+lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data) {
+  return nullptr;
+}
+
 void *
 lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data) {
   return nullptr;
@@ -302,6 +312,11 @@ lldb_private::python::SWIGBridge::ToSWIGWrapper(lldb::DataExtractorSP) {
   return python::PythonObject();
 }
 
+python::PythonObject
+lldb_private::python::SWIGBridge::ToSWIGWrapper(Event *event) {
+  return python::PythonObject();
+}
+
 python::PythonObject
 lldb_private::python::SWIGBridge::ToSWIGWrapper(const Stream *stream) {
   return python::PythonObject();



More information about the lldb-commits mailing list