[Lldb-commits] [lldb] f732157 - [lldb/Interpreter] Introduce ScriptedStopHook{, Python}Interface & make use of it (#109498)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Sep 20 16:55:51 PDT 2024
Author: Med Ismail Bennani
Date: 2024-09-20T16:55:47-07:00
New Revision: f732157a9d067e4d300905c831a964222e0eadee
URL: https://github.com/llvm/llvm-project/commit/f732157a9d067e4d300905c831a964222e0eadee
DIFF: https://github.com/llvm/llvm-project/commit/f732157a9d067e4d300905c831a964222e0eadee.diff
LOG: [lldb/Interpreter] Introduce ScriptedStopHook{,Python}Interface & make use of it (#109498)
This patch re-lands #105449 and fixes the various test failures.
---------
Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
Added:
lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h
Modified:
lldb/bindings/python/python-swigsafecast.swig
lldb/bindings/python/python-wrapper.swig
lldb/include/lldb/API/SBExecutionContext.h
lldb/include/lldb/Interpreter/ScriptInterpreter.h
lldb/include/lldb/Target/Target.h
lldb/include/lldb/lldb-forward.h
lldb/source/Interpreter/ScriptInterpreter.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
lldb/source/Target/Target.cpp
lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
Removed:
################################################################################
diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig
index 0127ac6bfa4681..7a4f7e81f1cc3b 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -33,7 +33,7 @@ PythonObject SWIGBridge::ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) {
SWIGTYPE_p_lldb__SBBreakpoint);
}
-PythonObject SWIGBridge::ToSWIGWrapper(Status status) {
+PythonObject SWIGBridge::ToSWIGWrapper(Status&& status) {
return ToSWIGHelper(new lldb::SBError(std::move(status)), SWIGTYPE_p_lldb__SBError);
}
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/Interfaces/ScriptedStopHookInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h
new file mode 100644
index 00000000000000..a829e62351fe85
--- /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..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();
@@ -561,6 +544,10 @@ class ScriptInterpreter : public PluginInterface {
return {};
}
+ virtual lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() {
+ return {};
+ }
+
virtual StructuredData::ObjectSP
CreateStructuredDataFromScriptObject(ScriptObject obj) {
return {};
@@ -587,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/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/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/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/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..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();
@@ -405,6 +428,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 +584,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/Interfaces/ScriptedStopHookPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp
new file mode 100644
index 00000000000000..eb052c24bab6da
--- /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..7f88098cb7fc70
--- /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/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 97a3837fd7aa62..81ee9ea0a2fa10 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -86,7 +86,7 @@ class SWIGBridge {
static PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp);
static PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp);
static PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp);
- static PythonObject ToSWIGWrapper(Status status);
+ static PythonObject ToSWIGWrapper(Status &&status);
static PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl);
static PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp);
static PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp);
@@ -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 63691d24f0dadb..155efc06eaf41a 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);
@@ -1654,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 85d79955e45efc..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;
@@ -112,6 +103,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
+ lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;
+
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
lldb::ScriptedThreadPlanInterfaceSP
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index f1659aae0800db..f9b6f7ded267ee 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,18 @@ 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);
+ lldb::StreamSP stream = std::make_shared<lldb_private::StreamString>();
+ auto should_stop_or_err = m_interface_sp->HandleStop(exc_ctx, stream);
+ output_sp->PutCString(
+ reinterpret_cast<StreamString *>(stream.get())->GetData());
+ 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/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
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index f2746c3e2516fd..c67a2b4bf46e64 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(Status &&status) {
return python::PythonObject();
}
More information about the lldb-commits
mailing list