diff options
author | Med Ismail Bennani <ismail@bennani.ma> | 2024-09-19 23:35:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-19 23:35:34 -0700 |
commit | 1e131ddfa8f1d7b18c85c6e4079458be8b419421 (patch) | |
tree | 6aac6c2d98fdb259657996ba7848949ddb3152a5 /lldb/source/Plugins/ScriptInterpreter/Python | |
parent | f9bd08382a4ad84c06e0b572d3b7fc3ecdb81898 (diff) | |
download | llvm-1e131ddfa8f1d7b18c85c6e4079458be8b419421.zip llvm-1e131ddfa8f1d7b18c85c6e4079458be8b419421.tar.gz llvm-1e131ddfa8f1d7b18c85c6e4079458be8b419421.tar.bz2 |
[lldb/Interpreter] Introduce `ScriptedStopHook{,Python}Interface` & make use of it (#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.
---------
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python')
10 files changed, 195 insertions, 76 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index 6ba714e..ee5e48a 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 38b6443..1fd3299 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 36b5214..26c80b7 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 a8e1d09..cf11c06 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 c715295..4b9f463 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -180,12 +180,35 @@ public: 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 @@ protected: 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 0000000..6cec7d6 --- /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 0000000..8548d8d --- /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 97a3837..8888a1e 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -157,16 +157,6 @@ public: 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 63691d2..155efc0 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 85d7995..d15e2fd 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -92,15 +92,6 @@ public: 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; lldb::ValueObjectListSP @@ -112,6 +103,8 @@ public: lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; + lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; lldb::ScriptedThreadPlanInterfaceSP |