[Lldb-commits] [lldb] [lldb/Interpreter] Introduce `ScriptedStopHook{, Python}Interface` & make use of it (PR #105449)
Med Ismail Bennani via lldb-commits
lldb-commits at lists.llvm.org
Tue Aug 20 16:41:17 PDT 2024
https://github.com/medismailben created https://github.com/llvm/llvm-project/pull/105449
This patch introduces new `ScriptedStopHook{,Python}Interface` classes that make use of the Scripted Interface infrastructure and makes use of it in `StopHookScripted`.
It also 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.
>From 78ca8b931a30d13a6817eeea562e15cf373465e1 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Tue, 20 Aug 2024 16:13:54 -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 <ismail at 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 | 50 +++++++++++++
.../Python/ScriptInterpreterPython.cpp | 5 ++
.../Python/ScriptInterpreterPythonImpl.h | 2 +
10 files changed, 176 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 89a480a28880aa..71fbb8487e246a 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -574,6 +574,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 337eff696fcf3f..874376e116efd5 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;
@@ -407,6 +408,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..9218cffb5131f9
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h
@@ -0,0 +1,50 @@
+//===-- 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<llvm::StringLiteral> GetAbstractMethods() const override {
+ return llvm::SmallVector<llvm::StringLiteral>({"handle_stop"});
+ }
+
+ 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 2a94f110910400..2292a2cea058f6 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1558,6 +1558,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 9ccbe07a70fe7e99c144d00e8a0f525bafddfc9c Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Tue, 20 Aug 2024 16:23:28 -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 <ismail at bennani.ma>
---
lldb/bindings/python/python-wrapper.swig | 109 +++---------------
lldb/include/lldb/API/SBExecutionContext.h | 2 +
.../lldb/Interpreter/ScriptInterpreter.h | 21 +---
lldb/include/lldb/Target/Target.h | 3 +-
lldb/source/Interpreter/ScriptInterpreter.cpp | 6 +
.../Interfaces/ScriptedPythonInterface.cpp | 18 +++
.../Interfaces/ScriptedPythonInterface.h | 9 ++
.../Python/SWIGPythonBridge.h | 11 +-
.../Python/ScriptInterpreterPython.cpp | 50 --------
lldb/source/Target/Target.cpp | 39 +++++--
.../Python/PythonTestSuite.cpp | 13 +--
11 files changed, 88 insertions(+), 193 deletions(-)
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 2ce42e3e017d5b..28f8e6c849437e 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -301,102 +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.SetErrorString("Empty class name.");
- return PythonObject();
- }
- if (!session_dictionary_name) {
- error.SetErrorString("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.SetErrorStringWithFormat("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.SetErrorStringWithFormat(
- "Wrong number of args for "
- "handle_stop callback, should be 2 (excluding self), got: %zu",
- num_args);
- return PythonObject();
- } else
- return result;
- } else {
- error.SetErrorString("Couldn't get num arguments for handle_stop "
- "callback.");
- return PythonObject();
- }
- return result;
- } else {
- error.SetErrorStringWithFormat("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(
@@ -675,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 71fbb8487e246a..e644719eb33d36 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"
@@ -277,23 +278,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.SetErrorString("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();
@@ -604,6 +588,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 7f4d607f5427df..7441eff3339817 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1387,8 +1387,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 fa23964a52ffeb..b4ababadaba7cf 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 699412e437a1ad..818c322ae22484 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -156,4 +156,22 @@ 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.SetErrorString("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 e1a3156d10afdb..d99e130730ae94 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -321,6 +321,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);
}
@@ -474,6 +478,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 5351c1a698b4a7..b430fc9967bc4f 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 2292a2cea058f6..de1bbb5c00d316 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1658,56 +1658,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.SetErrorString("No target for scripted stop-hook.");
- return StructuredData::GenericSP();
- }
-
- if (class_name == nullptr || class_name[0] == '\0') {
- error.SetErrorString("No class name for scripted stop-hook.");
- return StructuredData::GenericSP();
- }
-
- ScriptInterpreterPythonImpl *python_interpreter =
- GetPythonInterpreter(m_debugger);
-
- if (!python_interpreter) {
- error.SetErrorString("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/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 5a5d689e03fbc0..6df7c000877823 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"
@@ -3851,13 +3852,32 @@ Status Target::StopHookScripted::SetScriptCallback(
return error;
}
+ m_interface_sp = script_interp->CreateScriptedStopHookInterface();
+ if (!m_interface_sp) {
+ error.SetErrorStringWithFormat(
+ "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(obj_or_err.takeError());
+ }
- return error;
+ StructuredData::ObjectSP object_sp = *obj_or_err;
+ if (!object_sp || !object_sp->IsValid()) {
+ error.SetErrorStringWithFormat("ScriptedStopHook::%s () - ERROR: %s",
+ __FUNCTION__,
+ "Failed to create valid script object");
+ return error;
+ }
+
+ return {};
}
Target::StopHook::StopHookResult
@@ -3866,16 +3886,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/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 0edde54d310fdd..2b6dbf39ffb80b 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) {
@@ -268,14 +273,6 @@ void *lldb_private::python::SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
return nullptr;
}
-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) {
>From 83a173a3dc778566264db3078c47b5d8fe54f01e Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Tue, 20 Aug 2024 16:37:22 -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 <ismail at bennani.ma>
---
.../Interfaces/ScriptedPythonInterface.h | 28 +++++++++++++++----
.../dummy_scripted_process.py | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index d99e130730ae94..4da1cc79303436 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -137,12 +137,28 @@ 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);
+ 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(
+ llvm::formatv("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
More information about the lldb-commits
mailing list