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

>From 3387de37a8c0da9174653062b0804494d8ebf53e Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ism...@bennani.ma>
Date: Thu, 19 Sep 2024 23:29:13 -0700
Subject: [PATCH 1/3] [lldb/Interpreter] Create
 ScriptedStopHook{,Python}Interface (NFC)

This patch introduces a new scripted interface for ScriptedStopHooks.

This will be used in a follow-up patch to call into the script methods.

Signed-off-by: Med Ismail Bennani <ism...@bennani.ma>
---
 .../Interfaces/ScriptedStopHookInterface.h    | 33 ++++++++
 .../lldb/Interpreter/ScriptInterpreter.h      |  4 +
 lldb/include/lldb/lldb-forward.h              |  3 +
 .../Python/Interfaces/CMakeLists.txt          |  1 +
 .../ScriptInterpreterPythonInterfaces.cpp     |  2 +
 .../ScriptInterpreterPythonInterfaces.h       |  1 +
 .../ScriptedStopHookPythonInterface.cpp       | 75 +++++++++++++++++++
 .../ScriptedStopHookPythonInterface.h         | 51 +++++++++++++
 .../Python/ScriptInterpreterPython.cpp        |  5 ++
 .../Python/ScriptInterpreterPythonImpl.h      |  2 +
 10 files changed, 177 insertions(+)
 create mode 100644 
lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h
 create mode 100644 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
 create mode 100644 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h

diff --git 
a/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h 
b/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h
new file mode 100644
index 00000000000000..125e7f2077b543
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h
@@ -0,0 +1,33 @@
+//===-- ScriptedStopHookInterface.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_SCRIPTEDSTOPHOOKINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H
+
+#include "lldb/lldb-private.h"
+
+#include "ScriptedInterface.h"
+
+namespace lldb_private {
+class ScriptedStopHookInterface : public ScriptedInterface {
+public:
+  virtual llvm::Expected<StructuredData::GenericSP>
+  CreatePluginObject(llvm::StringRef class_name, lldb::TargetSP target_sp,
+                     const StructuredDataImpl &args_sp) = 0;
+
+  /// "handle_stop" will return a bool with the meaning "should_stop"...
+  /// If nothing is returned, we'll assume we are going to stop.
+  /// Also any errors should return true, since we should stop on error.
+  virtual llvm::Expected<bool> HandleStop(ExecutionContext &exe_ctx,
+                                          lldb::StreamSP output_sp) {
+    return true;
+  }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h 
b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index addb1394ab5652..8fabe6f250b084 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -561,6 +561,10 @@ class ScriptInterpreter : public PluginInterface {
     return {};
   }
 
+  virtual lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() {
+    return {};
+  }
+
   virtual StructuredData::ObjectSP
   CreateStructuredDataFromScriptObject(ScriptObject obj) {
     return {};
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 5fb288ad43af48..d09edeeccaff1a 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -190,6 +190,7 @@ class ScriptInterpreterLocker;
 class ScriptedMetadata;
 class ScriptedPlatformInterface;
 class ScriptedProcessInterface;
+class ScriptedStopHookInterface;
 class ScriptedThreadInterface;
 class ScriptedThreadPlanInterface;
 class ScriptedSyntheticChildren;
@@ -408,6 +409,8 @@ typedef 
std::unique_ptr<lldb_private::ScriptedPlatformInterface>
     ScriptedPlatformInterfaceUP;
 typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>
     ScriptedProcessInterfaceUP;
+typedef std::shared_ptr<lldb_private::ScriptedStopHookInterface>
+    ScriptedStopHookInterfaceSP;
 typedef std::shared_ptr<lldb_private::ScriptedThreadInterface>
     ScriptedThreadInterfaceSP;
 typedef std::shared_ptr<lldb_private::ScriptedThreadPlanInterface>
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
index 6ba714ed1c263e..ee5e48ad5cdc37 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
@@ -25,6 +25,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces 
PLUGIN
   ScriptedPlatformPythonInterface.cpp
   ScriptedProcessPythonInterface.cpp
   ScriptedPythonInterface.cpp
+  ScriptedStopHookPythonInterface.cpp
   ScriptedThreadPlanPythonInterface.cpp
   ScriptedThreadPythonInterface.cpp
 
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
index 38b644366080e4..1fd32993e385eb 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
@@ -28,6 +28,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() {
   OperatingSystemPythonInterface::Initialize();
   ScriptedPlatformPythonInterface::Initialize();
   ScriptedProcessPythonInterface::Initialize();
+  ScriptedStopHookPythonInterface::Initialize();
   ScriptedThreadPlanPythonInterface::Initialize();
 }
 
@@ -35,6 +36,7 @@ void ScriptInterpreterPythonInterfaces::Terminate() {
   OperatingSystemPythonInterface::Terminate();
   ScriptedPlatformPythonInterface::Terminate();
   ScriptedProcessPythonInterface::Terminate();
+  ScriptedStopHookPythonInterface::Terminate();
   ScriptedThreadPlanPythonInterface::Terminate();
 }
 
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
index 36b521480cc85c..26c80b75686918 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
@@ -18,6 +18,7 @@
 #include "OperatingSystemPythonInterface.h"
 #include "ScriptedPlatformPythonInterface.h"
 #include "ScriptedProcessPythonInterface.h"
+#include "ScriptedStopHookPythonInterface.h"
 #include "ScriptedThreadPlanPythonInterface.h"
 
 namespace lldb_private {
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
new file mode 100644
index 00000000000000..6cec7d6e7553d4
--- /dev/null
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
@@ -0,0 +1,75 @@
+//===-- ScriptedStopHookPythonInterface.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/Core/PluginManager.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// clang-format off
+// LLDB Python header must be included first
+#include "../lldb-python.h"
+//clang-format on
+
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
+#include "ScriptedStopHookPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+
+ScriptedStopHookPythonInterface::ScriptedStopHookPythonInterface(
+    ScriptInterpreterPythonImpl &interpreter)
+    : ScriptedStopHookInterface(), ScriptedPythonInterface(interpreter) {}
+
+llvm::Expected<StructuredData::GenericSP>
+ScriptedStopHookPythonInterface::CreatePluginObject(llvm::StringRef class_name,
+                                                    lldb::TargetSP target_sp,
+                                                    const StructuredDataImpl 
&args_sp) {
+  return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr,
+                                                     target_sp, args_sp);
+}
+
+llvm::Expected<bool>
+ScriptedStopHookPythonInterface::HandleStop(ExecutionContext &exe_ctx,
+                                            lldb::StreamSP output_sp) {
+  ExecutionContextRefSP exe_ctx_ref_sp =
+      std::make_shared<ExecutionContextRef>(exe_ctx);
+  Status error;
+  StructuredData::ObjectSP obj = Dispatch("handle_stop", error, 
exe_ctx_ref_sp, output_sp);
+
+  if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
+                                                    error)) {
+    if (!obj)
+      return true;
+    return error.ToError();
+  }
+
+  return obj->GetBooleanValue();
+}
+
+
+void ScriptedStopHookPythonInterface::Initialize() {
+  const std::vector<llvm::StringRef> ci_usages = {
+      "target stop-hook add -P <script-name> [-k key -v value ...]"};
+  const std::vector<llvm::StringRef> api_usages = {};
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(),
+      llvm::StringRef("Perform actions whenever the process stops, before 
control is returned to the user."),
+      CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
+}
+
+void ScriptedStopHookPythonInterface::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+#endif
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h
new file mode 100644
index 00000000000000..8548d8d7fcce0f
--- /dev/null
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h
@@ -0,0 +1,51 @@
+//===-- ScriptedStopHookPythonInterface.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_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H
+#define 
LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "ScriptedPythonInterface.h"
+
+namespace lldb_private {
+class ScriptedStopHookPythonInterface : public ScriptedStopHookInterface,
+                                        public ScriptedPythonInterface,
+                                        public PluginInterface {
+public:
+  ScriptedStopHookPythonInterface(ScriptInterpreterPythonImpl &interpreter);
+
+  llvm::Expected<StructuredData::GenericSP>
+  CreatePluginObject(llvm::StringRef class_name, lldb::TargetSP target_sp,
+                     const StructuredDataImpl &args_sp) override;
+
+  llvm::SmallVector<AbstractMethodRequirement>
+  GetAbstractMethodRequirements() const override {
+    return llvm::SmallVector<AbstractMethodRequirement>({{"handle_stop", 2}});
+  }
+
+  llvm::Expected<bool> HandleStop(ExecutionContext &exe_ctx,
+                                  lldb::StreamSP output_sp) override;
+
+  static void Initialize();
+
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() {
+    return "ScriptedStopHookPythonInterface";
+  }
+
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // 
LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp 
b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 63691d24f0dadb..fc144b1f7e3712 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1559,6 +1559,11 @@ 
ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {
   return std::make_unique<ScriptedProcessPythonInterface>(*this);
 }
 
+ScriptedStopHookInterfaceSP
+ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() {
+  return std::make_shared<ScriptedStopHookPythonInterface>(*this);
+}
+
 ScriptedThreadInterfaceSP
 ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
   return std::make_shared<ScriptedThreadPythonInterface>(*this);
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h 
b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 85d79955e45efc..16e2dde74aff3f 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -112,6 +112,8 @@ class ScriptInterpreterPythonImpl : public 
ScriptInterpreterPython {
 
   lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
 
+  lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;
+
   lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
 
   lldb::ScriptedThreadPlanInterfaceSP

>From 56ba282e72eeed97a3d441f88070ca8611b209cf Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ism...@bennani.ma>
Date: Thu, 19 Sep 2024 23:28:22 -0700
Subject: [PATCH 2/3] [lldb/Interpreter] Make use of
 ScriptedStopHook{,Python}Interface

This patch makes use of the previously defined
`ScriptedStopHook{,Python}Interface` in the `StopHookScripted` class and
removes all the SWIG methods that were implemented specifically for this.

Signed-off-by: Med Ismail Bennani <ism...@bennani.ma>
---
 lldb/bindings/python/python-wrapper.swig      | 111 ++----------------
 lldb/include/lldb/API/SBExecutionContext.h    |   2 +
 .../lldb/Interpreter/ScriptInterpreter.h      |  22 +---
 lldb/include/lldb/Target/Target.h             |   3 +-
 lldb/source/Interpreter/ScriptInterpreter.cpp |   6 +
 .../Interfaces/ScriptedPythonInterface.cpp    |  19 +++
 .../Interfaces/ScriptedPythonInterface.h      |   9 ++
 .../Python/SWIGPythonBridge.h                 |  11 +-
 .../Python/ScriptInterpreterPython.cpp        |  51 --------
 .../Python/ScriptInterpreterPythonImpl.h      |   9 --
 lldb/source/Target/Target.cpp                 |  39 ++++--
 .../target/stop-hooks/TestStopHookScripted.py |   4 +-
 .../Python/PythonTestSuite.cpp                |  21 +---
 13 files changed, 92 insertions(+), 215 deletions(-)

diff --git a/lldb/bindings/python/python-wrapper.swig 
b/lldb/bindings/python/python-wrapper.swig
index 810673aaec5d19..961fb2d1a76178 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -301,104 +301,6 @@ unsigned int 
lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResol
   return ret_val;
 }
 
-PythonObject 
lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook(
-    lldb::TargetSP target_sp, const char *python_class_name,
-    const char *session_dictionary_name, const StructuredDataImpl &args_impl,
-    Status &error) {
-  if (python_class_name == NULL || python_class_name[0] == '\0') {
-    error = Status::FromErrorString("Empty class name.");
-    return PythonObject();
-  }
-  if (!session_dictionary_name) {
-    error = Status::FromErrorString("No session dictionary");
-    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 = Status::FromErrorStringWithFormat("Could not find class: %s.",
-                                   python_class_name);
-    return PythonObject();
-  }
-
-  PythonObject result =
-      pfunc(SWIGBridge::ToSWIGWrapper(target_sp), 
SWIGBridge::ToSWIGWrapper(args_impl), dict);
-
-  if (result.IsAllocated()) {
-    // Check that the handle_stop callback is defined:
-    auto callback_func = result.ResolveName<PythonCallable>("handle_stop");
-    if (callback_func.IsAllocated()) {
-      if (auto args_info = callback_func.GetArgInfo()) {
-        size_t num_args = (*args_info).max_positional_args;
-        if (num_args != 2) {
-          error = Status::FromErrorStringWithFormat(
-              "Wrong number of args for "
-              "handle_stop callback, should be 2 (excluding self), got: %zu",
-              num_args);
-          return PythonObject();
-        } else
-          return result;
-      } else {
-        error = Status::FromErrorString(
-            "Couldn't get num arguments for handle_stop "
-            "callback.");
-        return PythonObject();
-      }
-      return result;
-    } else {
-      error = Status::FromErrorStringWithFormat(
-          "Class \"%s\" is missing the required "
-          "handle_stop callback.",
-          python_class_name);
-    }
-  }
-  return PythonObject();
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
-    void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp,
-    lldb::StreamSP stream) {
-  // handle_stop will return a bool with the meaning "should_stop"...
-  // If you return nothing we'll assume we are going to stop.
-  // Also any errors should return true, since we should stop on error.
-
-  PyErr_Cleaner py_err_cleaner(false);
-  PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
-  auto pfunc = self.ResolveName<PythonCallable>("handle_stop");
-
-  if (!pfunc.IsAllocated())
-    return true;
-
-  std::shared_ptr<lldb::SBStream> sb_stream = 
std::make_shared<lldb::SBStream>();
-  PythonObject sb_stream_arg = SWIGBridge::ToSWIGWrapper(sb_stream);
-  PythonObject result =
-      pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg);
-
-  if (PyErr_Occurred()) {
-    stream->PutCString("Python error occurred handling stop-hook.");
-    PyErr_Print();
-    PyErr_Clear();
-    return true;
-  }
-
-  // Now add the result to the output stream.  SBStream only
-  // makes an internally help StreamString which I can't interpose, so I
-  // have to copy it over here.
-  stream->PutCString(sb_stream->GetData());
-  sb_stream_arg.release();
-
-  if (result.get() == Py_False)
-    return false;
-  else
-    return true;
-}
-
 // wrapper that calls an optional instance member of an object taking no
 // arguments
 static PyObject *LLDBSwigPython_CallOptionalMember(
@@ -677,6 +579,19 @@ void 
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyOb
   return sb_ptr;
 }
 
+void 
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject 
*
+                                                                    data) {
+  lldb::SBExecutionContext *sb_ptr = NULL;
+
+  int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr,
+                                   SWIGTYPE_p_lldb__SBExecutionContext, 0);
+
+  if (valid_cast == -1)
+    return NULL;
+
+  return sb_ptr;
+}
+
 bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand(
     const char *python_function_name, const char *session_dictionary_name,
     lldb::DebuggerSP debugger, const char *args,
diff --git a/lldb/include/lldb/API/SBExecutionContext.h 
b/lldb/include/lldb/API/SBExecutionContext.h
index e8de2ebe58785e..e1e08fe3f4aae4 100644
--- a/lldb/include/lldb/API/SBExecutionContext.h
+++ b/lldb/include/lldb/API/SBExecutionContext.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 namespace lldb_private {
+class ScriptInterpreter;
 namespace python {
 class SWIGBridge;
 }
@@ -55,6 +56,7 @@ class LLDB_API SBExecutionContext {
 
 protected:
   friend class lldb_private::python::SWIGBridge;
+  friend class lldb_private::ScriptInterpreter;
 
   lldb_private::ExecutionContextRef *get() const;
 
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h 
b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 8fabe6f250b084..901ecf3012d51d 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -14,6 +14,7 @@
 #include "lldb/API/SBData.h"
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBEvent.h"
+#include "lldb/API/SBExecutionContext.h"
 #include "lldb/API/SBLaunchInfo.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
 #include "lldb/API/SBStream.h"
@@ -271,24 +272,6 @@ class ScriptInterpreter : public PluginInterface {
     return lldb::eSearchDepthModule;
   }
 
-  virtual StructuredData::GenericSP
-  CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
-                         const StructuredDataImpl &args_data, Status &error) {
-    error =
-        Status::FromErrorString("Creating scripted stop-hooks with the current 
"
-                                "script interpreter is not supported.");
-    return StructuredData::GenericSP();
-  }
-
-  // This dispatches to the handle_stop method of the stop-hook class.  It
-  // returns a "should_stop" bool.
-  virtual bool
-  ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
-                             ExecutionContext &exc_ctx,
-                             lldb::StreamSP stream_sp) {
-    return true;
-  }
-
   virtual StructuredData::ObjectSP
   LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
     return StructuredData::ObjectSP();
@@ -591,6 +574,9 @@ class ScriptInterpreter : public PluginInterface {
   std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo(
       const lldb::SBMemoryRegionInfo &mem_region) const;
 
+  lldb::ExecutionContextRefSP GetOpaqueTypeFromSBExecutionContext(
+      const lldb::SBExecutionContext &exe_ctx) const;
+
 protected:
   Debugger &m_debugger;
   lldb::ScriptLanguage m_script_lang;
diff --git a/lldb/include/lldb/Target/Target.h 
b/lldb/include/lldb/Target/Target.h
index 50df01aac74004..e4848f19e64d62 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1391,8 +1391,7 @@ class Target : public 
std::enable_shared_from_this<Target>,
     /// This holds the dictionary of keys & values that can be used to
     /// parametrize any given callback's behavior.
     StructuredDataImpl m_extra_args;
-    /// This holds the python callback object.
-    StructuredData::GenericSP m_implementation_sp;
+    lldb::ScriptedStopHookInterfaceSP m_interface_sp;
 
     /// Use CreateStopHook to make a new empty stop hook. The GetCommandPointer
     /// and fill it with commands, and SetSpecifier to set the specifier shared
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp 
b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 8b55221da6e761..559b8301c10106 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -125,6 +125,12 @@ ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
   return *mem_region.m_opaque_up.get();
 }
 
+lldb::ExecutionContextRefSP
+ScriptInterpreter::GetOpaqueTypeFromSBExecutionContext(
+    const lldb::SBExecutionContext &exe_ctx) const {
+  return exe_ctx.m_exe_ctx_sp;
+}
+
 lldb::ScriptLanguage
 ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
   if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index a8e1d09da0bf12..cf11c06e8a95d4 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -159,4 +159,23 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<
   return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info);
 }
 
+template <>
+lldb::ExecutionContextRefSP
+ScriptedPythonInterface::ExtractValueFromPythonObject<
+    lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error) {
+
+  lldb::SBExecutionContext *sb_exe_ctx =
+      reinterpret_cast<lldb::SBExecutionContext *>(
+          python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(p.get()));
+
+  if (!sb_exe_ctx) {
+    error = Status::FromErrorStringWithFormat(
+        "Couldn't cast lldb::SBExecutionContext to "
+        "lldb::ExecutionContextRefSP.");
+    return {};
+  }
+
+  return m_interpreter.GetOpaqueTypeFromSBExecutionContext(*sb_exe_ctx);
+}
+
 #endif
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index c715295eb9ff02..5378dd21b0baa3 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -405,6 +405,10 @@ class ScriptedPythonInterface : virtual public 
ScriptedInterface {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
 
+  python::PythonObject Transform(lldb::TargetSP arg) {
+    return python::SWIGBridge::ToSWIGWrapper(arg);
+  }
+
   python::PythonObject Transform(lldb::ProcessSP arg) {
     return python::SWIGBridge::ToSWIGWrapper(arg);
   }
@@ -557,6 +561,11 @@ std::optional<MemoryRegionInfo>
 ScriptedPythonInterface::ExtractValueFromPythonObject<
     std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
 
+template <>
+lldb::ExecutionContextRefSP
+ScriptedPythonInterface::ExtractValueFromPythonObject<
+    lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error);
+
 } // namespace lldb_private
 
 #endif // LLDB_ENABLE_PYTHON
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h 
b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 97a3837fd7aa62..8888a1e415deba 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -157,16 +157,6 @@ class SWIGBridge {
                                        const char *method_name,
                                        lldb_private::SymbolContext *sym_ctx);
 
-  static python::PythonObject LLDBSwigPythonCreateScriptedStopHook(
-      lldb::TargetSP target_sp, const char *python_class_name,
-      const char *session_dictionary_name, const StructuredDataImpl &args,
-      lldb_private::Status &error);
-
-  static bool
-  LLDBSwigPythonStopHookCallHandleStop(void *implementor,
-                                       lldb::ExecutionContextRefSP exc_ctx,
-                                       lldb::StreamSP stream);
-
   static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor,
                                                     uint32_t max);
 
@@ -266,6 +256,7 @@ void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
 void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
+void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data);
 } // namespace python
 
 } // namespace lldb_private
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp 
b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index fc144b1f7e3712..155efc06eaf41a 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1659,57 +1659,6 @@ 
ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth(
   return lldb::eSearchDepthModule;
 }
 
-StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook(
-    TargetSP target_sp, const char *class_name,
-    const StructuredDataImpl &args_data, Status &error) {
-
-  if (!target_sp) {
-    error = Status::FromErrorString("No target for scripted stop-hook.");
-    return StructuredData::GenericSP();
-  }
-
-  if (class_name == nullptr || class_name[0] == '\0') {
-    error = Status::FromErrorString("No class name for scripted stop-hook.");
-    return StructuredData::GenericSP();
-  }
-
-  ScriptInterpreterPythonImpl *python_interpreter =
-      GetPythonInterpreter(m_debugger);
-
-  if (!python_interpreter) {
-    error = Status::FromErrorString(
-        "No script interpreter for scripted stop-hook.");
-    return StructuredData::GenericSP();
-  }
-
-  Locker py_lock(this,
-                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
-  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedStopHook(
-      target_sp, class_name, python_interpreter->m_dictionary_name.c_str(),
-      args_data, error);
-
-  return StructuredData::GenericSP(
-      new StructuredPythonObject(std::move(ret_val)));
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop(
-    StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx,
-    lldb::StreamSP stream_sp) {
-  assert(implementor_sp &&
-         "can't call a stop hook with an invalid implementor");
-  assert(stream_sp && "can't call a stop hook with an invalid stream");
-
-  Locker py_lock(this,
-                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
-  lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx));
-
-  bool ret_val = SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
-      implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp);
-  return ret_val;
-}
-
 StructuredData::ObjectSP
 ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
                                               lldb_private::Status &error) {
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h 
b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 16e2dde74aff3f..d15e2fd76f683b 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -91,15 +91,6 @@ class ScriptInterpreterPythonImpl : public 
ScriptInterpreterPython {
   lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
       StructuredData::GenericSP implementor_sp) override;
 
-  StructuredData::GenericSP
-  CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
-                         const StructuredDataImpl &args_data,
-                         Status &error) override;
-
-  bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
-                                  ExecutionContext &exc_ctx,
-                                  lldb::StreamSP stream_sp) override;
-
   StructuredData::GenericSP
   CreateFrameRecognizer(const char *class_name) override;
 
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index f1659aae0800db..14c7702e2f5fbc 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -36,6 +36,7 @@
 #include "lldb/Host/StreamFile.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h"
 #include "lldb/Interpreter/OptionGroupWatchpoint.h"
 #include "lldb/Interpreter/OptionValues.h"
 #include "lldb/Interpreter/Property.h"
@@ -3868,13 +3869,32 @@ Status Target::StopHookScripted::SetScriptCallback(
     return error;
   }
 
+  m_interface_sp = script_interp->CreateScriptedStopHookInterface();
+  if (!m_interface_sp) {
+    error = Status::FromErrorStringWithFormat(
+        "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__,
+        "Script interpreter couldn't create Scripted Stop Hook Interface");
+    return error;
+  }
+
   m_class_name = class_name;
   m_extra_args.SetObjectSP(extra_args_sp);
 
-  m_implementation_sp = script_interp->CreateScriptedStopHook(
-      GetTarget(), m_class_name.c_str(), m_extra_args, error);
+  auto obj_or_err = m_interface_sp->CreatePluginObject(
+      m_class_name, GetTarget(), m_extra_args);
+  if (!obj_or_err) {
+    return Status::FromError(obj_or_err.takeError());
+  }
 
-  return error;
+  StructuredData::ObjectSP object_sp = *obj_or_err;
+  if (!object_sp || !object_sp->IsValid()) {
+    error = Status::FromErrorStringWithFormat(
+        "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__,
+        "Failed to create valid script object");
+    return error;
+  }
+
+  return {};
 }
 
 Target::StopHook::StopHookResult
@@ -3883,16 +3903,15 @@ Target::StopHookScripted::HandleStop(ExecutionContext 
&exc_ctx,
   assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context "
                                    "with no target");
 
-  ScriptInterpreter *script_interp =
-      GetTarget()->GetDebugger().GetScriptInterpreter();
-  if (!script_interp)
+  if (!m_interface_sp)
     return StopHookResult::KeepStopped;
 
-  bool should_stop = script_interp->ScriptedStopHookHandleStop(
-      m_implementation_sp, exc_ctx, output_sp);
+  auto should_stop_or_err = m_interface_sp->HandleStop(exc_ctx, output_sp);
+  if (!should_stop_or_err)
+    return StopHookResult::KeepStopped;
 
-  return should_stop ? StopHookResult::KeepStopped
-                     : StopHookResult::RequestContinue;
+  return *should_stop_or_err ? StopHookResult::KeepStopped
+                             : StopHookResult::RequestContinue;
 }
 
 void Target::StopHookScripted::GetSubclassDescription(
diff --git a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py 
b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
index b865fd0c0a44f3..7c10669442b1c2 100644
--- a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
+++ b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
@@ -32,7 +32,7 @@ def test_bad_handler(self):
         self.interp.HandleCommand(command, result)
         self.assertFalse(result.Succeeded(), "Set the target stop hook")
         self.assertIn(
-            "Wrong number of args",
+            "has unexpected argument count",
             result.GetError(),
             "Got the wrong number of args error",
         )
@@ -43,7 +43,7 @@ def test_bad_handler(self):
         self.interp.HandleCommand(command, result)
         self.assertFalse(result.Succeeded(), "Set the target stop hook")
         self.assertIn(
-            'Class "stop_hook.no_handle_stop" is missing the required 
handle_stop callback',
+            "Abstract method no_handle_stop.handle_stop not implemented",
             result.GetError(),
             "Got the right error",
         )
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp 
b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index f2746c3e2516fd..ef9df053323aa5 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -154,6 +154,11 @@ void 
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(
   return nullptr;
 }
 
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(
+    PyObject *data) {
+  return nullptr;
+}
+
 lldb::ValueObjectSP
 lldb_private::python::SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(
     void *data) {
@@ -269,21 +274,7 @@ void 
*lldb_private::python::SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
 }
 
 python::PythonObject
-lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook(
-    lldb::TargetSP target_sp, const char *python_class_name,
-    const char *session_dictionary_name, const StructuredDataImpl &args_impl,
-    Status &error) {
-  return python::PythonObject();
-}
-
-bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
-    void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp,
-    lldb::StreamSP stream) {
-  return false;
-}
-
-python::PythonObject
-lldb_private::python::SWIGBridge::ToSWIGWrapper(Status status) {
+lldb_private::python::SWIGBridge::ToSWIGWrapper(const Status &status) {
   return python::PythonObject();
 }
 

>From 855da31d29fa3adc4bec831e0a185a982256a30c Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ism...@bennani.ma>
Date: Thu, 19 Sep 2024 23:23:52 -0700
Subject: [PATCH 3/3] [lldb/Interpreter] Relax Scripted Interface object
 creation requirements

Historically, some scripted extension would pass the embedded
interpreter session dictionary as a argument of the extension
initializer.

In many cases, that argument ended up not being used but was still
required for all new extension implementations.

This patch relax this requirement by checking if the number of maximum
positional argument is 1 argument more then the number of argument
passed in the parameter pack, in which case it will pass the interpreter
session dictionary with the rest of the arguments. If the implementation
doesn't have it in the initializer, only the paramater pack is passed to it.

Signed-off-by: Med Ismail Bennani <ism...@bennani.ma>
---
 .../Interfaces/ScriptedPythonInterface.h      | 35 +++++++++++++++----
 .../dummy_scripted_process.py                 |  2 +-
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 5378dd21b0baa3..4b9f463ef5605d 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -180,12 +180,35 @@ class ScriptedPythonInterface : virtual public 
ScriptedInterface {
       llvm::Expected<PythonObject> expected_return_object =
           create_error("Resulting object is not initialized.");
 
-      std::apply(
-          [&init, &expected_return_object](auto &&...args) {
-            llvm::consumeError(expected_return_object.takeError());
-            expected_return_object = init(args...);
-          },
-          transformed_args);
+      // This relax the requirement on the number of argument for
+      // initializing scripting extension if the size of the interface
+      // parameter pack contains 1 less element than the extension maximum
+      // number of positional arguments for this initializer.
+      //
+      // This addresses the cases where the embedded interpreter session
+      // dictionary is passed to the extension initializer which is not used
+      // most of the time.
+      size_t num_args = sizeof...(Args);
+      if (num_args != arg_info->max_positional_args) {
+        if (num_args != arg_info->max_positional_args - 1)
+          return create_error("Passed arguments ({0}) doesn't match the number 
"
+                              "of expected arguments ({1}).",
+                              num_args, arg_info->max_positional_args);
+
+        std::apply(
+            [&init, &expected_return_object](auto &&...args) {
+              llvm::consumeError(expected_return_object.takeError());
+              expected_return_object = init(args...);
+            },
+            std::tuple_cat(transformed_args, std::make_tuple(dict)));
+      } else {
+        std::apply(
+            [&init, &expected_return_object](auto &&...args) {
+              llvm::consumeError(expected_return_object.takeError());
+              expected_return_object = init(args...);
+            },
+            transformed_args);
+      }
 
       if (!expected_return_object)
         return expected_return_object.takeError();
diff --git 
a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py 
b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
index cb07bf32c5080e..2721d961bcb9d5 100644
--- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -8,7 +8,7 @@
 
 
 class DummyStopHook:
-    def __init__(self, target, args, internal_dict):
+    def __init__(self, target, args):
         self.target = target
         self.args = args
 

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to