From b1c73532ee8997fe5dfbeb7d223027bdf99758a0 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 9 Dec 2023 14:28:42 +0100 Subject: Vendor import of llvm-project main llvmorg-18-init-14265-ga17671084db1. --- .../Interfaces/OperatingSystemPythonInterface.cpp | 82 ++++ .../Interfaces/OperatingSystemPythonInterface.h | 48 +++ .../Interfaces/ScriptedPlatformPythonInterface.cpp | 94 +++++ .../Interfaces/ScriptedPlatformPythonInterface.h | 50 +++ .../Interfaces/ScriptedProcessPythonInterface.cpp | 202 +++++++++ .../Interfaces/ScriptedProcessPythonInterface.h | 76 ++++ .../Python/Interfaces/ScriptedPythonInterface.cpp | 137 +++++++ .../Python/Interfaces/ScriptedPythonInterface.h | 456 +++++++++++++++++++++ .../Interfaces/ScriptedThreadPythonInterface.cpp | 137 +++++++ .../Interfaces/ScriptedThreadPythonInterface.h | 57 +++ .../ScriptInterpreter/Python/PythonDataObjects.cpp | 20 +- .../ScriptInterpreter/Python/PythonDataObjects.h | 2 + .../ScriptInterpreter/Python/SWIGPythonBridge.h | 6 - .../Python/ScriptInterpreterPython.cpp | 211 ++-------- .../Python/ScriptInterpreterPythonImpl.h | 18 +- .../Python/ScriptedPlatformPythonInterface.cpp | 108 ----- .../Python/ScriptedPlatformPythonInterface.h | 44 -- .../Python/ScriptedProcessPythonInterface.cpp | 216 ---------- .../Python/ScriptedProcessPythonInterface.h | 71 ---- .../Python/ScriptedPythonInterface.cpp | 137 ------- .../Python/ScriptedPythonInterface.h | 257 ------------ .../Python/ScriptedThreadPythonInterface.cpp | 159 ------- .../Python/ScriptedThreadPythonInterface.h | 52 --- 23 files changed, 1393 insertions(+), 1247 deletions(-) create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp delete mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h (limited to 'lldb/source/Plugins/ScriptInterpreter/Python') diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp new file mode 100644 index 000000000000..c162c7367c65 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp @@ -0,0 +1,82 @@ +//===-- ScriptedThreadPythonInterface.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "../lldb-python.h" + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "OperatingSystemPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +OperatingSystemPythonInterface::OperatingSystemPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {} + +llvm::Expected +OperatingSystemPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + exe_ctx.GetProcessSP()); +} + +StructuredData::DictionarySP +OperatingSystemPythonInterface::CreateThread(lldb::tid_t tid, + lldb::addr_t context) { + Status error; + StructuredData::DictionarySP dict = Dispatch( + "create_thread", error, tid, context); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +StructuredData::ArraySP OperatingSystemPythonInterface::GetThreadInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch("get_thread_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +StructuredData::DictionarySP OperatingSystemPythonInterface::GetRegisterInfo() { + return ScriptedThreadPythonInterface::GetRegisterInfo(); +} + +std::optional +OperatingSystemPythonInterface::GetRegisterContextForTID(lldb::tid_t tid) { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_register_data", error, tid); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetAsString()->GetValue().str(); +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h new file mode 100644 index 000000000000..da7bbf13b1d5 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h @@ -0,0 +1,48 @@ +//===-- OperatingSystemPythonInterface.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedThreadPythonInterface.h" +#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h" +#include + +namespace lldb_private { +class OperatingSystemPythonInterface + : virtual public OperatingSystemInterface, + virtual public ScriptedThreadPythonInterface { +public: + OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector GetAbstractMethods() const override { + return llvm::SmallVector({"get_thread_info"}); + } + + StructuredData::DictionarySP CreateThread(lldb::tid_t tid, + lldb::addr_t context) override; + + StructuredData::ArraySP GetThreadInfo() override; + + StructuredData::DictionarySP GetRegisterInfo() override; + + std::optional GetRegisterContextForTID(lldb::tid_t tid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp new file mode 100644 index 000000000000..9ba4731032bd --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp @@ -0,0 +1,94 @@ +//===-- ScriptedPlatformPythonInterface.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "../lldb-python.h" + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedPlatformPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedPlatformPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared(exe_ctx); + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); +} + +StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch("list_processes", error); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +StructuredData::DictionarySP +ScriptedPlatformPythonInterface::GetProcessInfo(lldb::pid_t pid) { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch("get_process_info", error, pid); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +Status ScriptedPlatformPythonInterface::AttachToProcess( + ProcessAttachInfoSP attach_info) { + // FIXME: Pass `attach_info` to method call + return GetStatusFromMethod("attach_to_process"); +} + +Status ScriptedPlatformPythonInterface::LaunchProcess( + ProcessLaunchInfoSP launch_info) { + // FIXME: Pass `launch_info` to method call + return GetStatusFromMethod("launch_process"); +} + +Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) { + return GetStatusFromMethod("kill_process", pid); +} + +#endif // LLDB_ENABLE_PYTHON diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h new file mode 100644 index 000000000000..0842d3a00342 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h @@ -0,0 +1,50 @@ +//===-- ScriptedPlatformPythonInterface.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_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h" + +namespace lldb_private { +class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, + public ScriptedPythonInterface { +public: + ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector GetAbstractMethods() const override { + return llvm::SmallVector( + {"list_processes", "attach_to_process", "launch_process", + "kill_process"}); + } + + StructuredData::DictionarySP ListProcesses() override; + + StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; + + Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) override; + + Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override; + + Status KillProcess(lldb::pid_t pid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp new file mode 100644 index 000000000000..e86b34d6b930 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp @@ -0,0 +1,202 @@ +//===-- ScriptedProcessPythonInterface.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#if LLDB_ENABLE_PYTHON +// LLDB Python header must be included first +#include "../lldb-python.h" +#endif +#include "lldb/Target/Process.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedProcessPythonInterface.h" +#include "ScriptedThreadPythonInterface.h" +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedProcessPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared(exe_ctx); + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_capabilities", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + +Status +ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { + lldb::ProcessAttachInfoSP attach_info_sp = + std::make_shared(attach_info); + return GetStatusFromMethod("attach", attach_info_sp); +} + +Status ScriptedProcessPythonInterface::Launch() { + return GetStatusFromMethod("launch"); +} + +Status ScriptedProcessPythonInterface::Resume() { + // When calling ScriptedProcess.Resume from lldb we should always stop. + return GetStatusFromMethod("resume", /*should_stop=*/true); +} + +std::optional +ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( + lldb::addr_t address, Status &error) { + auto mem_region = Dispatch>( + "get_memory_region_containing_address", error, address); + + if (error.Fail()) { + return ErrorWithMessage(LLVM_PRETTY_FUNCTION, + error.AsCString(), error); + } + + return mem_region; +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_threads_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + +bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr, + Status &error) { + Status py_error; + StructuredData::ObjectSP obj = + Dispatch("create_breakpoint", py_error, addr, error); + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetBooleanValue(); +} + +lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( + lldb::addr_t address, size_t size, Status &error) { + Status py_error; + lldb::DataExtractorSP data_sp = Dispatch( + "read_memory_at_address", py_error, address, size, error); + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + return data_sp; +} + +lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( + lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) { + Status py_error; + StructuredData::ObjectSP obj = + Dispatch("write_memory_at_address", py_error, addr, data_sp, error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return LLDB_INVALID_OFFSET; + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); +} + +StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { + Status error; + StructuredData::ArraySP array = + Dispatch("get_loaded_images", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, error)) + return {}; + + return array; +} + +lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_process_id", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return LLDB_INVALID_PROCESS_ID; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); +} + +bool ScriptedProcessPythonInterface::IsAlive() { + Status error; + StructuredData::ObjectSP obj = Dispatch("is_alive", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetBooleanValue(); +} + +std::optional +ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetStringValue().str(); +} + +lldb::ScriptedThreadInterfaceSP +ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { + return m_interpreter.CreateScriptedThreadInterface(); +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_process_metadata", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h new file mode 100644 index 000000000000..c75caa9340f2 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h @@ -0,0 +1,76 @@ +//===-- ScriptedProcessPythonInterface.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_SCRIPTEDPROCESSPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" +#include + +namespace lldb_private { +class ScriptedProcessPythonInterface : public ScriptedProcessInterface, + public ScriptedPythonInterface { +public: + ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector GetAbstractMethods() const override { + return llvm::SmallVector( + {"read_memory_at_address", "is_alive", "get_scripted_thread_plugin"}); + } + + StructuredData::DictionarySP GetCapabilities() override; + + Status Attach(const ProcessAttachInfo &attach_info) override; + + Status Launch() override; + + Status Resume() override; + + std::optional + GetMemoryRegionContainingAddress(lldb::addr_t address, + Status &error) override; + + StructuredData::DictionarySP GetThreadsInfo() override; + + bool CreateBreakpoint(lldb::addr_t addr, Status &error) override; + + lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, + Status &error) override; + + lldb::offset_t WriteMemoryAtAddress(lldb::addr_t addr, + lldb::DataExtractorSP data_sp, + Status &error) override; + + StructuredData::ArraySP GetLoadedImages() override; + + lldb::pid_t GetProcessID() override; + + bool IsAlive() override; + + std::optional GetScriptedThreadPluginName() override; + + StructuredData::DictionarySP GetMetadata() override; + +private: + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp new file mode 100644 index 000000000000..6f22503b279c --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -0,0 +1,137 @@ +//===-- ScriptedPythonInterface.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "../lldb-python.h" + +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedPythonInterface.h" +#include + +using namespace lldb; +using namespace lldb_private; + +ScriptedPythonInterface::ScriptedPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedInterface(), m_interpreter(interpreter) {} + +template <> +StructuredData::ArraySP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + python::PythonList result_list(python::PyRefType::Borrowed, p.get()); + return result_list.CreateStructuredArray(); +} + +template <> +StructuredData::DictionarySP +ScriptedPythonInterface::ExtractValueFromPythonObject< + StructuredData::DictionarySP>(python::PythonObject &p, Status &error) { + python::PythonDictionary result_dict(python::PyRefType::Borrowed, p.get()); + return result_dict.CreateStructuredDictionary(); +} + +template <> +Status ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + if (lldb::SBError *sb_error = reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBError(p.get()))) + return m_interpreter.GetStatusFromSBError(*sb_error); + else + error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); + + return {}; +} + +template <> +lldb::DataExtractorSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBData *sb_data = reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBData(p.get())); + + if (!sb_data) { + error.SetErrorString( + "Couldn't cast lldb::SBData to lldb::DataExtractorSP."); + return nullptr; + } + + return m_interpreter.GetDataExtractorFromSBData(*sb_data); +} + +template <> +lldb::BreakpointSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBBreakpoint(p.get())); + + if (!sb_breakpoint) { + error.SetErrorString( + "Couldn't cast lldb::SBBreakpoint to lldb::BreakpointSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBBreakpoint(*sb_breakpoint); +} + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBAttachInfo *sb_attach_info = reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get())); + + if (!sb_attach_info) { + error.SetErrorString( + "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info); +} + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get())); + + if (!sb_launch_info) { + error.SetErrorString( + "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info); +} + +template <> +std::optional +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::optional>(python::PythonObject &p, Status &error) { + + lldb::SBMemoryRegionInfo *sb_mem_reg_info = + reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); + + if (!sb_mem_reg_info) { + error.SetErrorString( + "Couldn't cast lldb::SBMemoryRegionInfo to lldb::MemoryRegionInfoSP."); + return {}; + } + + return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info); +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h new file mode 100644 index 000000000000..163659234466 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -0,0 +1,456 @@ +//===-- ScriptedPythonInterface.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_SCRIPTEDPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H + +#if LLDB_ENABLE_PYTHON + +#include +#include +#include +#include +#include + +#include "lldb/Host/Config.h" +#include "lldb/Interpreter/Interfaces/ScriptedInterface.h" +#include "lldb/Utility/DataBufferHeap.h" + +#include "../PythonDataObjects.h" +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" + +namespace lldb_private { +class ScriptInterpreterPythonImpl; +class ScriptedPythonInterface : virtual public ScriptedInterface { +public: + ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); + ~ScriptedPythonInterface() override = default; + + enum class AbstractMethodCheckerCases { + eNotImplemented, + eNotAllocated, + eNotCallable, + eValid + }; + + llvm::Expected> + CheckAbstractMethodImplementation( + const python::PythonDictionary &class_dict) const { + + using namespace python; + + std::map checker; +#define SET_ERROR_AND_CONTINUE(method_name, error) \ + { \ + checker[method_name] = error; \ + continue; \ + } + + for (const llvm::StringLiteral &method_name : GetAbstractMethods()) { + if (!class_dict.HasKey(method_name)) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotImplemented) + auto callable_or_err = class_dict.GetItem(method_name); + if (!callable_or_err) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotAllocated) + if (!PythonCallable::Check(callable_or_err.get().get())) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotCallable) + checker[method_name] = AbstractMethodCheckerCases::eValid; + } + +#undef HANDLE_ERROR + + return checker; + } + + template + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, + StructuredData::Generic *script_obj, Args... args) { + using namespace python; + using Locker = ScriptInterpreterPythonImpl::Locker; + + auto create_error = [](std::string message) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), message); + }; + + bool has_class_name = !class_name.empty(); + bool has_interpreter_dict = + !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty()); + if (!has_class_name && !has_interpreter_dict && !script_obj) { + if (!has_class_name) + return create_error("Missing script class name."); + else if (!has_interpreter_dict) + return create_error("Invalid script interpreter dictionary."); + else + return create_error("Missing scripting object."); + } + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + PythonObject result = {}; + + if (script_obj) { + result = PythonObject(PyRefType::Borrowed, + static_cast(script_obj->GetValue())); + } else { + auto dict = + PythonModule::MainModule().ResolveName( + m_interpreter.GetDictionaryName()); + if (!dict.IsAllocated()) + return create_error( + llvm::formatv("Could not find interpreter dictionary: %s", + m_interpreter.GetDictionaryName())); + + auto init = + PythonObject::ResolveNameWithDictionary( + class_name, dict); + if (!init.IsAllocated()) + return create_error(llvm::formatv("Could not find script class: %s", + class_name.data())); + + std::tuple original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + std::string error_string; + llvm::Expected arg_info = init.GetArgInfo(); + if (!arg_info) { + llvm::handleAllErrors( + arg_info.takeError(), + [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, + [&](const llvm::ErrorInfoBase &E) { + error_string.append(E.message()); + }); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + error_string); + } + + llvm::Expected 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); + + if (!expected_return_object) + return expected_return_object.takeError(); + result = expected_return_object.get(); + } + + if (!result.IsValid()) + return create_error("Resulting object is not a valid Python Object."); + if (!result.HasAttribute("__class__")) + return create_error("Resulting object doesn't have '__class__' member."); + + PythonObject obj_class = result.GetAttributeValue("__class__"); + if (!obj_class.IsValid()) + return create_error("Resulting class object is not a valid."); + if (!obj_class.HasAttribute("__name__")) + return create_error( + "Resulting object class doesn't have '__name__' member."); + PythonString obj_class_name = + obj_class.GetAttributeValue("__name__").AsType(); + + PythonObject object_class_mapping_proxy = + obj_class.GetAttributeValue("__dict__"); + if (!obj_class.HasAttribute("__dict__")) + return create_error( + "Resulting object class doesn't have '__dict__' member."); + + PythonCallable dict_converter = PythonModule::BuiltinsModule() + .ResolveName("dict") + .AsType(); + if (!dict_converter.IsAllocated()) + return create_error( + "Python 'builtins' module doesn't have 'dict' class."); + + PythonDictionary object_class_dict = + dict_converter(object_class_mapping_proxy).AsType(); + if (!object_class_dict.IsAllocated()) + return create_error("Coudn't create dictionary from resulting object " + "class mapping proxy object."); + + auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict); + if (!checker_or_err) + return checker_or_err.takeError(); + + for (const auto &method_checker : *checker_or_err) + switch (method_checker.second) { + case AbstractMethodCheckerCases::eNotImplemented: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not implemented.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eNotAllocated: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not allocated.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eNotCallable: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not callable.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eValid: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} implemented & valid.", + obj_class_name.GetString(), method_checker.first); + break; + } + + for (const auto &method_checker : *checker_or_err) + if (method_checker.second != AbstractMethodCheckerCases::eValid) + return create_error( + llvm::formatv("Abstract method {0}.{1} missing. Enable lldb " + "script log for more details.", + obj_class_name.GetString(), method_checker.first)); + + m_object_instance_sp = StructuredData::GenericSP( + new StructuredPythonObject(std::move(result))); + return m_object_instance_sp; + } + +protected: + template + T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { + return p.CreateStructuredObject(); + } + + template + T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { + using namespace python; + using Locker = ScriptInterpreterPythonImpl::Locker; + + std::string caller_signature = + llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + + llvm::Twine(method_name) + llvm::Twine(")")) + .str(); + if (!m_object_instance_sp) + return ErrorWithMessage(caller_signature, "Python object ill-formed", + error); + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + PythonObject implementor(PyRefType::Borrowed, + (PyObject *)m_object_instance_sp->GetValue()); + + if (!implementor.IsAllocated()) + return ErrorWithMessage(caller_signature, + "Python implementor not allocated.", error); + + std::tuple original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + llvm::Expected expected_return_object = + llvm::make_error("Not initialized.", + llvm::inconvertibleErrorCode()); + std::apply( + [&implementor, &method_name, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = + implementor.CallMethod(method_name.data(), args...); + }, + transformed_args); + + if (llvm::Error e = expected_return_object.takeError()) { + error.SetErrorString(llvm::toString(std::move(e)).c_str()); + return ErrorWithMessage(caller_signature, + "Python method could not be called.", error); + } + + PythonObject py_return = std::move(expected_return_object.get()); + + // Now that we called the python method with the transformed arguments, + // we need to interate again over both the original and transformed + // parameter pack, and transform back the parameter that were passed in + // the original parameter pack as references or pointers. + if (sizeof...(Args) > 0) + if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) + return ErrorWithMessage( + caller_signature, + "Couldn't re-assign reference and pointer arguments.", error); + + if (!py_return.IsAllocated()) + return {}; + return ExtractValueFromPythonObject(py_return, error); + } + + template + Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { + Status error; + Dispatch(method_name, error, std::forward(args)...); + + return error; + } + + template T Transform(T object) { + // No Transformation for generic usage + return {object}; + } + + python::PythonObject Transform(bool arg) { + // Boolean arguments need to be turned into python objects. + return python::PythonBoolean(arg); + } + + python::PythonObject Transform(Status arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(const StructuredDataImpl &arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ExecutionContextRefSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::DataExtractorSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + template + void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { + // If U is not a PythonObject, don't touch it! + return; + } + + template + void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, + Status &error) { + original_arg = ExtractValueFromPythonObject(transformed_arg, error); + } + + void ReverseTransform(bool &original_arg, + python::PythonObject transformed_arg, Status &error) { + python::PythonBoolean boolean_arg = python::PythonBoolean( + python::PyRefType::Borrowed, transformed_arg.get()); + if (boolean_arg.IsValid()) + original_arg = boolean_arg.GetValue(); + else + error.SetErrorString( + llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION) + .str()); + } + + template + auto TransformTuple(const std::tuple &args, + std::index_sequence) { + return std::make_tuple(Transform(std::get(args))...); + } + + // This will iterate over the Dispatch parameter pack and replace in-place + // every `lldb_private` argument that has a SB counterpart. + template + auto TransformArgs(const std::tuple &args) { + return TransformTuple(args, std::make_index_sequence()); + } + + template + void TransformBack(T &original_arg, U transformed_arg, Status &error) { + ReverseTransform(original_arg, transformed_arg, error); + } + + template + bool ReassignPtrsOrRefsArgs(std::tuple &original_args, + std::tuple &transformed_args, + std::index_sequence) { + Status error; + (TransformBack(std::get(original_args), std::get(transformed_args), + error), + ...); + return error.Success(); + } + + template + bool ReassignPtrsOrRefsArgs(std::tuple &original_args, + std::tuple &transformed_args) { + if (sizeof...(Ts) != sizeof...(Us)) + return false; + + return ReassignPtrsOrRefsArgs(original_args, transformed_args, + std::make_index_sequence()); + } + + template + void FormatArgs(std::string &fmt, T arg, Args... args) const { + FormatArgs(fmt, arg); + FormatArgs(fmt, args...); + } + + template void FormatArgs(std::string &fmt, T arg) const { + fmt += python::PythonFormat::format; + } + + void FormatArgs(std::string &fmt) const {} + + // The lifetime is managed by the ScriptInterpreter + ScriptInterpreterPythonImpl &m_interpreter; +}; + +template <> +StructuredData::ArraySP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +StructuredData::DictionarySP +ScriptedPythonInterface::ExtractValueFromPythonObject< + StructuredData::DictionarySP>(python::PythonObject &p, Status &error); + +template <> +Status ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::BreakpointSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); + +template <> +lldb::DataExtractorSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +std::optional +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::optional>(python::PythonObject &p, Status &error); + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp new file mode 100644 index 000000000000..18e268527eb2 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp @@ -0,0 +1,137 @@ +//===-- ScriptedThreadPythonInterface.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "../lldb-python.h" + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedThreadPythonInterface.h" +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedThreadPythonInterface::ScriptedThreadPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedThreadInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedThreadPythonInterface::CreatePluginObject( + const llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared(exe_ctx); + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); +} + +lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_thread_id", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return LLDB_INVALID_THREAD_ID; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); +} + +std::optional ScriptedThreadPythonInterface::GetName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_name", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetStringValue().str(); +} + +lldb::StateType ScriptedThreadPythonInterface::GetState() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_state", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return eStateInvalid; + + return static_cast(obj->GetUnsignedIntegerValue(eStateInvalid)); +} + +std::optional ScriptedThreadPythonInterface::GetQueue() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_queue", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetStringValue().str(); +} + +StructuredData::DictionarySP ScriptedThreadPythonInterface::GetStopReason() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_stop_reason", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + +StructuredData::ArraySP ScriptedThreadPythonInterface::GetStackFrames() { + Status error; + StructuredData::ArraySP arr = + Dispatch("get_stackframes", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) + return {}; + + return arr; +} + +StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_register_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + +std::optional ScriptedThreadPythonInterface::GetRegisterContext() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_register_context", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return {}; + + return obj->GetAsString()->GetValue().str(); +} + +StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch("get_extended_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) + return {}; + + return arr; +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h new file mode 100644 index 000000000000..5676f7f1d675 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h @@ -0,0 +1,57 @@ +//===-- ScriptedThreadPythonInterface.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_SCRIPTEDTHREADPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" +#include + +namespace lldb_private { +class ScriptedThreadPythonInterface : public ScriptedThreadInterface, + public ScriptedPythonInterface { +public: + ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector GetAbstractMethods() const override { + return llvm::SmallVector( + {"get_stop_reason", "get_register_context"}); + } + + lldb::tid_t GetThreadID() override; + + std::optional GetName() override; + + lldb::StateType GetState() override; + + std::optional GetQueue() override; + + StructuredData::DictionarySP GetStopReason() override; + + StructuredData::ArraySP GetStackFrames() override; + + StructuredData::DictionarySP GetRegisterInfo() override; + + std::optional GetRegisterContext() override; + + StructuredData::ArraySP GetExtendedInfo() override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index eee2f6f5d43f..ea0a1cdff40f 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -71,7 +71,9 @@ Expected python::As(Expected &&obj) { } static bool python_is_finalizing() { -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13) || (PY_MAJOR_VERSION > 3) + return Py_IsFinalizing(); +#elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 return _Py_Finalizing != nullptr; #else return _Py_IsFinalizing(); @@ -661,6 +663,20 @@ bool PythonDictionary::Check(PyObject *py_obj) { return PyDict_Check(py_obj); } +bool PythonDictionary::HasKey(const llvm::Twine &key) const { + if (!IsValid()) + return false; + + PythonString key_object(key.isSingleStringRef() ? key.getSingleStringRef() + : key.str()); + + if (int res = PyDict_Contains(m_py_obj, key_object.get()) > 0) + return res; + + PyErr_Print(); + return false; +} + uint32_t PythonDictionary::GetSize() const { if (IsValid()) return PyDict_Size(m_py_obj); @@ -1344,7 +1360,7 @@ llvm::Expected PythonFile::ConvertToFile(bool borrowed) { FileSP file_sp; if (borrowed) { - // In this case we we don't need to retain the python + // In this case we don't need to retain the python // object at all. file_sp = std::make_shared(fd, options.get(), false); } else { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 012f16e95e77..82eee76e42b2 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -562,6 +562,8 @@ public: static bool Check(PyObject *py_obj); + bool HasKey(const llvm::Twine &key) const; + uint32_t GetSize() const; PythonList GetKeys() const; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 630ab293cf93..7cdd5577919b 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -116,12 +116,6 @@ public: // callbacks. Although these are scripting-language specific, their definition // depends on the public API. - static python::PythonObject LLDBSwigPythonCreateScriptedObject( - const char *python_class_name, const char *session_dictionary_name, - lldb::ExecutionContextRefSP exe_ctx_sp, - const lldb_private::StructuredDataImpl &args_impl, - std::string &error_string); - static llvm::Expected LLDBSwigPythonBreakpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 55b7a73712c4..ef7a2c128a22 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -14,12 +14,14 @@ // LLDB Python header must be included first #include "lldb-python.h" +#include "Interfaces/OperatingSystemPythonInterface.h" +#include "Interfaces/ScriptedPlatformPythonInterface.h" +#include "Interfaces/ScriptedProcessPythonInterface.h" +#include "Interfaces/ScriptedThreadPythonInterface.h" #include "PythonDataObjects.h" #include "PythonReadline.h" #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" -#include "ScriptedPlatformPythonInterface.h" -#include "ScriptedProcessPythonInterface.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFrame.h" @@ -177,18 +179,31 @@ private: return; #endif +// `PyEval_ThreadsInitialized` was deprecated in Python 3.9 and removed in +// Python 3.13. It has been returning `true` always since Python 3.7. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3) if (PyEval_ThreadsInitialized()) { +#else + if (true) { +#endif Log *log = GetLog(LLDBLog::Script); m_was_already_initialized = true; m_gil_state = PyGILState_Ensure(); LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n", m_gil_state == PyGILState_UNLOCKED ? "un" : ""); + +// `PyEval_InitThreads` was deprecated in Python 3.9 and removed in +// Python 3.13. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3) return; } // InitThreads acquires the GIL if it hasn't been called before. PyEval_InitThreads(); +#else + } +#endif } PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; @@ -412,8 +427,6 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { - m_scripted_platform_interface_up = - std::make_unique(*this); m_dictionary_name.append("_dict"); StreamString run_string; @@ -582,10 +595,6 @@ void ScriptInterpreterPythonImpl::LeaveSession() { // up believing we have no thread state and PyImport_AddModule will crash if // that is the case - since that seems to only happen when destroying the // SBDebugger, we can make do without clearing up stdout and stderr - - // rdar://problem/11292882 - // When the current thread state is NULL, PyThreadState_Get() issues a fatal - // error. if (PyThreadState_GetDict()) { PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { @@ -1519,6 +1528,16 @@ ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() { return std::make_unique(*this); } +ScriptedThreadInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { + return std::make_shared(*this); +} + +OperatingSystemInterfaceSP +ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() { + return std::make_shared(*this); +} + StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( ScriptObject obj) { @@ -1530,159 +1549,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( return py_obj.CreateStructuredObject(); } -StructuredData::GenericSP -ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( - const char *class_name, lldb::ProcessSP process_sp) { - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!process_sp) - return StructuredData::GenericSP(); - - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = SWIGBridge::LLDBSWIGPythonCreateOSPlugin( - class_name, m_dictionary_name.c_str(), process_sp); - - return StructuredData::GenericSP( - new StructuredPythonObject(std::move(ret_val))); -} - -StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( - StructuredData::ObjectSP os_plugin_object_sp) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected expected_py_return = - implementor.CallMethod("get_register_info"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); - return result_dict.CreateStructuredDictionary(); - } - return StructuredData::DictionarySP(); -} - -StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( - StructuredData::ObjectSP os_plugin_object_sp) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected expected_py_return = - implementor.CallMethod("get_thread_info"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonList result_list(PyRefType::Borrowed, py_return.get()); - return result_list.CreateStructuredArray(); - } - return StructuredData::ArraySP(); -} - -StructuredData::StringSP -ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( - StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected expected_py_return = - implementor.CallMethod("get_register_data", tid); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonBytes result(PyRefType::Borrowed, py_return.get()); - return result.CreateStructuredString(); - } - return {}; -} - -StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( - StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, - lldb::addr_t context) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected expected_py_return = - implementor.CallMethod("create_thread", tid, context); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); - return result_dict.CreateStructuredDictionary(); - } - return StructuredData::DictionarySP(); -} - StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( const char *class_name, const StructuredDataImpl &args_data, std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) { @@ -1783,7 +1649,7 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( bool ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription( - StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, + StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, bool &script_error) { StructuredData::Generic *generic = nullptr; if (implementor_sp) @@ -2442,24 +2308,11 @@ ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( } PythonObject py_return = std::move(expected_py_return.get()); + if (!py_return.IsAllocated() || !PythonString::Check(py_return.get())) + return {}; - ConstString ret_val; - bool got_string = false; - std::string buffer; - - if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { - PythonString py_string(PyRefType::Borrowed, py_return.get()); - llvm::StringRef return_data(py_string.GetString()); - if (!return_data.empty()) { - buffer.assign(return_data.data(), return_data.size()); - got_string = true; - } - } - - if (got_string) - ret_val.SetCStringWithLength(buffer.c_str(), buffer.size()); - - return ret_val; + PythonString type_name(PyRefType::Borrowed, py_return.get()); + return ConstString(type_name.GetString()); } bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 01db6c520300..a33499816d8d 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -134,23 +134,9 @@ public: lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; - StructuredData::GenericSP - OSPlugin_CreatePluginObject(const char *class_name, - lldb::ProcessSP process_sp) override; - - StructuredData::DictionarySP - OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; - StructuredData::ArraySP - OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::StringSP - OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t thread_id) override; - - StructuredData::DictionarySP - OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t tid, lldb::addr_t context) override; + lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override; StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp deleted file mode 100644 index a0c55874c70a..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//===-- ScriptedPlatformPythonInterface.cpp -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" -#include "ScriptedPlatformPythonInterface.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::python; -using Locker = ScriptInterpreterPythonImpl::Locker; - -ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface( - ScriptInterpreterPythonImpl &interpreter) - : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {} - -StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject( - llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty()) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - lldb::ExecutionContextRefSP exe_ctx_ref_sp = - std::make_shared(exe_ctx); - - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; -} - -StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() { - Status error; - StructuredData::DictionarySP dict_sp = - Dispatch("list_processes", error); - - if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { - return ScriptedInterface::ErrorWithMessage( - LLVM_PRETTY_FUNCTION, - llvm::Twine("Null or invalid object (" + - llvm::Twine(error.AsCString()) + llvm::Twine(").")) - .str(), - error); - } - - return dict_sp; -} - -StructuredData::DictionarySP -ScriptedPlatformPythonInterface::GetProcessInfo(lldb::pid_t pid) { - Status error; - StructuredData::DictionarySP dict_sp = - Dispatch("get_process_info", error, pid); - - if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { - return ScriptedInterface::ErrorWithMessage( - LLVM_PRETTY_FUNCTION, - llvm::Twine("Null or invalid object (" + - llvm::Twine(error.AsCString()) + llvm::Twine(").")) - .str(), - error); - } - - return dict_sp; -} - -Status ScriptedPlatformPythonInterface::AttachToProcess( - ProcessAttachInfoSP attach_info) { - // FIXME: Pass `attach_info` to method call - return GetStatusFromMethod("attach_to_process"); -} - -Status ScriptedPlatformPythonInterface::LaunchProcess( - ProcessLaunchInfoSP launch_info) { - // FIXME: Pass `launch_info` to method call - return GetStatusFromMethod("launch_process"); -} - -Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) { - return GetStatusFromMethod("kill_process", pid); -} - -#endif // LLDB_ENABLE_PYTHON diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h deleted file mode 100644 index 1e3ad9962325..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- ScriptedPlatformPythonInterface.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_SCRIPTEDPLATFORMPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H - -#include "lldb/Host/Config.h" - -#if LLDB_ENABLE_PYTHON - -#include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedPlatformInterface.h" - -namespace lldb_private { -class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, - public ScriptedPythonInterface { -public: - ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter); - - StructuredData::GenericSP - CreatePluginObject(const llvm::StringRef class_name, - ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, - StructuredData::Generic *script_obj = nullptr) override; - - StructuredData::DictionarySP ListProcesses() override; - - StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; - - Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) override; - - Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override; - - Status KillProcess(lldb::pid_t pid) override; -}; -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp deleted file mode 100644 index 019924fa1971..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ /dev/null @@ -1,216 +0,0 @@ -//===-- ScriptedProcessPythonInterface.cpp --------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#if LLDB_ENABLE_PYTHON -// LLDB Python header must be included first -#include "lldb-python.h" -#endif -#include "lldb/Target/Process.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" -#include "ScriptedProcessPythonInterface.h" -#include "ScriptedThreadPythonInterface.h" -#include - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::python; -using Locker = ScriptInterpreterPythonImpl::Locker; - -ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( - ScriptInterpreterPythonImpl &interpreter) - : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} - -StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( - llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty()) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - lldb::ExecutionContextRefSP exe_ctx_ref_sp = - std::make_shared(exe_ctx); - - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; -} - -StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { - Status error; - StructuredData::DictionarySP dict = - Dispatch("get_capabilities", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) - return {}; - - return dict; -} - -Status -ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { - lldb::ProcessAttachInfoSP attach_info_sp = - std::make_shared(attach_info); - return GetStatusFromMethod("attach", attach_info_sp); -} - -Status ScriptedProcessPythonInterface::Launch() { - return GetStatusFromMethod("launch"); -} - -Status ScriptedProcessPythonInterface::Resume() { - // When calling ScriptedProcess.Resume from lldb we should always stop. - return GetStatusFromMethod("resume", /*should_stop=*/true); -} - -std::optional -ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( - lldb::addr_t address, Status &error) { - auto mem_region = Dispatch>( - "get_memory_region_containing_address", error, address); - - if (error.Fail()) { - return ErrorWithMessage(LLVM_PRETTY_FUNCTION, - error.AsCString(), error); - } - - return mem_region; -} - -StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { - Status error; - StructuredData::DictionarySP dict = - Dispatch("get_threads_info", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) - return {}; - - return dict; -} - -bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr, - Status &error) { - Status py_error; - StructuredData::ObjectSP obj = - Dispatch("create_breakpoint", py_error, addr, error); - - // If there was an error on the python call, surface it to the user. - if (py_error.Fail()) - error = py_error; - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetBooleanValue(); -} - -lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( - lldb::addr_t address, size_t size, Status &error) { - Status py_error; - lldb::DataExtractorSP data_sp = Dispatch( - "read_memory_at_address", py_error, address, size, error); - - // If there was an error on the python call, surface it to the user. - if (py_error.Fail()) - error = py_error; - - return data_sp; -} - -lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( - lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) { - Status py_error; - StructuredData::ObjectSP obj = - Dispatch("write_memory_at_address", py_error, addr, data_sp, error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return LLDB_INVALID_OFFSET; - - // If there was an error on the python call, surface it to the user. - if (py_error.Fail()) - error = py_error; - - return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); -} - -StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { - Status error; - StructuredData::ArraySP array = - Dispatch("get_loaded_images", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, error)) - return {}; - - return array; -} - -lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_process_id", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return LLDB_INVALID_PROCESS_ID; - - return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); -} - -bool ScriptedProcessPythonInterface::IsAlive() { - Status error; - StructuredData::ObjectSP obj = Dispatch("is_alive", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetBooleanValue(); -} - -std::optional -ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetStringValue().str(); -} - -lldb::ScriptedThreadInterfaceSP -ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { - return std::make_shared(m_interpreter); -} - -StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { - Status error; - StructuredData::DictionarySP dict = - Dispatch("get_process_metadata", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) - return {}; - - return dict; -} - -#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h deleted file mode 100644 index ff03eab07648..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ /dev/null @@ -1,71 +0,0 @@ -//===-- ScriptedProcessPythonInterface.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_SCRIPTEDPROCESSPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H - -#include "lldb/Host/Config.h" - -#if LLDB_ENABLE_PYTHON - -#include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedProcessInterface.h" -#include - -namespace lldb_private { -class ScriptedProcessPythonInterface : public ScriptedProcessInterface, - public ScriptedPythonInterface { -public: - ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter); - - StructuredData::GenericSP - CreatePluginObject(const llvm::StringRef class_name, - ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, - StructuredData::Generic *script_obj = nullptr) override; - - StructuredData::DictionarySP GetCapabilities() override; - - Status Attach(const ProcessAttachInfo &attach_info) override; - - Status Launch() override; - - Status Resume() override; - - std::optional - GetMemoryRegionContainingAddress(lldb::addr_t address, - Status &error) override; - - StructuredData::DictionarySP GetThreadsInfo() override; - - bool CreateBreakpoint(lldb::addr_t addr, Status &error) override; - - lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, - Status &error) override; - - lldb::offset_t WriteMemoryAtAddress(lldb::addr_t addr, - lldb::DataExtractorSP data_sp, - Status &error) override; - - StructuredData::ArraySP GetLoadedImages() override; - - lldb::pid_t GetProcessID() override; - - bool IsAlive() override; - - std::optional GetScriptedThreadPluginName() override; - - StructuredData::DictionarySP GetMetadata() override; - -private: - lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; -}; -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp deleted file mode 100644 index 1e36a81fde54..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//===-- ScriptedPythonInterface.cpp ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#include "lldb/Utility/Log.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "ScriptInterpreterPythonImpl.h" -#include "ScriptedPythonInterface.h" -#include - -using namespace lldb; -using namespace lldb_private; - -ScriptedPythonInterface::ScriptedPythonInterface( - ScriptInterpreterPythonImpl &interpreter) - : ScriptedInterface(), m_interpreter(interpreter) {} - -template <> -StructuredData::ArraySP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error) { - python::PythonList result_list(python::PyRefType::Borrowed, p.get()); - return result_list.CreateStructuredArray(); -} - -template <> -StructuredData::DictionarySP -ScriptedPythonInterface::ExtractValueFromPythonObject< - StructuredData::DictionarySP>(python::PythonObject &p, Status &error) { - python::PythonDictionary result_dict(python::PyRefType::Borrowed, p.get()); - return result_dict.CreateStructuredDictionary(); -} - -template <> -Status ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error) { - if (lldb::SBError *sb_error = reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBError(p.get()))) - return m_interpreter.GetStatusFromSBError(*sb_error); - else - error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); - - return {}; -} - -template <> -lldb::DataExtractorSP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error) { - lldb::SBData *sb_data = reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBData(p.get())); - - if (!sb_data) { - error.SetErrorString( - "Couldn't cast lldb::SBData to lldb::DataExtractorSP."); - return nullptr; - } - - return m_interpreter.GetDataExtractorFromSBData(*sb_data); -} - -template <> -lldb::BreakpointSP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error) { - lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBBreakpoint(p.get())); - - if (!sb_breakpoint) { - error.SetErrorString( - "Couldn't cast lldb::SBBreakpoint to lldb::BreakpointSP."); - return nullptr; - } - - return m_interpreter.GetOpaqueTypeFromSBBreakpoint(*sb_breakpoint); -} - -template <> -lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< - lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) { - lldb::SBAttachInfo *sb_attach_info = reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get())); - - if (!sb_attach_info) { - error.SetErrorString( - "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP."); - return nullptr; - } - - return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info); -} - -template <> -lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< - lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) { - lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get())); - - if (!sb_launch_info) { - error.SetErrorString( - "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP."); - return nullptr; - } - - return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info); -} - -template <> -std::optional -ScriptedPythonInterface::ExtractValueFromPythonObject< - std::optional>(python::PythonObject &p, Status &error) { - - lldb::SBMemoryRegionInfo *sb_mem_reg_info = - reinterpret_cast( - python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); - - if (!sb_mem_reg_info) { - error.SetErrorString( - "Couldn't cast lldb::SBMemoryRegionInfo to lldb::MemoryRegionInfoSP."); - return {}; - } - - return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info); -} - -#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h deleted file mode 100644 index 4d0645d18aca..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ /dev/null @@ -1,257 +0,0 @@ -//===-- ScriptedPythonInterface.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_SCRIPTEDPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H - -#if LLDB_ENABLE_PYTHON - -#include -#include -#include -#include -#include - -#include "lldb/Host/Config.h" -#include "lldb/Interpreter/ScriptedInterface.h" -#include "lldb/Utility/DataBufferHeap.h" - -#include "PythonDataObjects.h" -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" - -namespace lldb_private { -class ScriptInterpreterPythonImpl; -class ScriptedPythonInterface : virtual public ScriptedInterface { -public: - ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); - ~ScriptedPythonInterface() override = default; - -protected: - template - T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { - return p.CreateStructuredObject(); - } - - template - T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { - using namespace python; - using Locker = ScriptInterpreterPythonImpl::Locker; - - std::string caller_signature = - llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + - llvm::Twine(method_name) + llvm::Twine(")")) - .str(); - if (!m_object_instance_sp) - return ErrorWithMessage(caller_signature, "Python object ill-formed", - error); - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)m_object_instance_sp->GetValue()); - - if (!implementor.IsAllocated()) - return ErrorWithMessage(caller_signature, - "Python implementor not allocated.", error); - - std::tuple original_args = std::forward_as_tuple(args...); - auto transformed_args = TransformArgs(original_args); - - llvm::Expected expected_return_object = - llvm::make_error("Not initialized.", - llvm::inconvertibleErrorCode()); - std::apply( - [&implementor, &method_name, &expected_return_object](auto &&...args) { - llvm::consumeError(expected_return_object.takeError()); - expected_return_object = - implementor.CallMethod(method_name.data(), args...); - }, - transformed_args); - - if (llvm::Error e = expected_return_object.takeError()) { - error.SetErrorString(llvm::toString(std::move(e)).c_str()); - return ErrorWithMessage(caller_signature, - "Python method could not be called.", error); - } - - PythonObject py_return = std::move(expected_return_object.get()); - - if (!py_return.IsAllocated()) - return ErrorWithMessage(caller_signature, "Returned object is null.", - error); - - // Now that we called the python method with the transformed arguments, - // we need to interate again over both the original and transformed - // parameter pack, and transform back the parameter that were passed in - // the original parameter pack as references or pointers. - if (sizeof...(Args) > 0) - if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) - return ErrorWithMessage( - caller_signature, - "Couldn't re-assign reference and pointer arguments.", error); - - return ExtractValueFromPythonObject(py_return, error); - } - - template - Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { - Status error; - Dispatch(method_name, error, std::forward(args)...); - - return error; - } - - template T Transform(T object) { - // No Transformation for generic usage - return {object}; - } - - python::PythonObject Transform(bool arg) { - // Boolean arguments need to be turned into python objects. - return python::PythonBoolean(arg); - } - - python::PythonObject Transform(Status arg) { - return python::SWIGBridge::ToSWIGWrapper(arg); - } - - python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { - return python::SWIGBridge::ToSWIGWrapper(arg); - } - - python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { - return python::SWIGBridge::ToSWIGWrapper(arg); - } - - python::PythonObject Transform(lldb::DataExtractorSP arg) { - return python::SWIGBridge::ToSWIGWrapper(arg); - } - - template - void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { - // If U is not a PythonObject, don't touch it! - return; - } - - template - void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, - Status &error) { - original_arg = ExtractValueFromPythonObject(transformed_arg, error); - } - - - void ReverseTransform(bool &original_arg, - python::PythonObject transformed_arg, Status &error) { - python::PythonBoolean boolean_arg = python::PythonBoolean( - python::PyRefType::Borrowed, transformed_arg.get()); - if (boolean_arg.IsValid()) - original_arg = boolean_arg.GetValue(); - else - error.SetErrorString( - llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION) - .str()); - } - - template - auto TransformTuple(const std::tuple &args, - std::index_sequence) { - return std::make_tuple(Transform(std::get(args))...); - } - - // This will iterate over the Dispatch parameter pack and replace in-place - // every `lldb_private` argument that has a SB counterpart. - template - auto TransformArgs(const std::tuple &args) { - return TransformTuple(args, std::make_index_sequence()); - } - - template - void TransformBack(T &original_arg, U transformed_arg, Status &error) { - ReverseTransform(original_arg, transformed_arg, error); - } - - template - bool ReassignPtrsOrRefsArgs(std::tuple &original_args, - std::tuple &transformed_args, - std::index_sequence) { - Status error; - (TransformBack(std::get(original_args), std::get(transformed_args), - error), - ...); - return error.Success(); - } - - template - bool ReassignPtrsOrRefsArgs(std::tuple &original_args, - std::tuple &transformed_args) { - if (sizeof...(Ts) != sizeof...(Us)) - return false; - - return ReassignPtrsOrRefsArgs(original_args, transformed_args, - std::make_index_sequence()); - } - - template - void FormatArgs(std::string &fmt, T arg, Args... args) const { - FormatArgs(fmt, arg); - FormatArgs(fmt, args...); - } - - template void FormatArgs(std::string &fmt, T arg) const { - fmt += python::PythonFormat::format; - } - - void FormatArgs(std::string &fmt) const {} - - // The lifetime is managed by the ScriptInterpreter - ScriptInterpreterPythonImpl &m_interpreter; -}; - -template <> -StructuredData::ArraySP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error); - -template <> -StructuredData::DictionarySP -ScriptedPythonInterface::ExtractValueFromPythonObject< - StructuredData::DictionarySP>(python::PythonObject &p, Status &error); - -template <> -Status ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error); - -template <> -lldb::BreakpointSP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error); - -template <> -lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< - lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); - -template <> -lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< - lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); - -template <> -lldb::DataExtractorSP -ScriptedPythonInterface::ExtractValueFromPythonObject( - python::PythonObject &p, Status &error); - -template <> -std::optional -ScriptedPythonInterface::ExtractValueFromPythonObject< - std::optional>(python::PythonObject &p, Status &error); - -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp deleted file mode 100644 index 5603a1541314..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ /dev/null @@ -1,159 +0,0 @@ -//===-- ScriptedThreadPythonInterface.cpp ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#include "lldb/Utility/Log.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" -#include "ScriptedThreadPythonInterface.h" -#include - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::python; -using Locker = ScriptInterpreterPythonImpl::Locker; - -ScriptedThreadPythonInterface::ScriptedThreadPythonInterface( - ScriptInterpreterPythonImpl &interpreter) - : ScriptedThreadInterface(), ScriptedPythonInterface(interpreter) {} - -StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( - const llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty() && !script_obj) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - PythonObject ret_val; - - if (!script_obj) { - lldb::ExecutionContextRefSP exe_ctx_ref_sp = - std::make_shared(exe_ctx); - ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - } else - ret_val = PythonObject(PyRefType::Borrowed, - static_cast(script_obj->GetValue())); - - if (!ret_val) - return {}; - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; -} - -lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_thread_id", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return LLDB_INVALID_THREAD_ID; - - return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); -} - -std::optional ScriptedThreadPythonInterface::GetName() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_name", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetStringValue().str(); -} - -lldb::StateType ScriptedThreadPythonInterface::GetState() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_state", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return eStateInvalid; - - return static_cast(obj->GetUnsignedIntegerValue(eStateInvalid)); -} - -std::optional ScriptedThreadPythonInterface::GetQueue() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_queue", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetStringValue().str(); -} - -StructuredData::DictionarySP ScriptedThreadPythonInterface::GetStopReason() { - Status error; - StructuredData::DictionarySP dict = - Dispatch("get_stop_reason", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) - return {}; - - return dict; -} - -StructuredData::ArraySP ScriptedThreadPythonInterface::GetStackFrames() { - Status error; - StructuredData::ArraySP arr = - Dispatch("get_stackframes", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) - return {}; - - return arr; -} - -StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() { - Status error; - StructuredData::DictionarySP dict = - Dispatch("get_register_info", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) - return {}; - - return dict; -} - -std::optional ScriptedThreadPythonInterface::GetRegisterContext() { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_register_context", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) - return {}; - - return obj->GetAsString()->GetValue().str(); -} - -StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { - Status error; - StructuredData::ArraySP arr = - Dispatch("get_extended_info", error); - - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) - return {}; - - return arr; -} - -#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h deleted file mode 100644 index eac4941f8814..000000000000 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h +++ /dev/null @@ -1,52 +0,0 @@ -//===-- ScriptedThreadPythonInterface.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_SCRIPTEDTHREADPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H - -#include "lldb/Host/Config.h" - -#if LLDB_ENABLE_PYTHON - -#include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedProcessInterface.h" -#include - -namespace lldb_private { -class ScriptedThreadPythonInterface : public ScriptedThreadInterface, - public ScriptedPythonInterface { -public: - ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter); - - StructuredData::GenericSP - CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp, - StructuredData::Generic *script_obj = nullptr) override; - - lldb::tid_t GetThreadID() override; - - std::optional GetName() override; - - lldb::StateType GetState() override; - - std::optional GetQueue() override; - - StructuredData::DictionarySP GetStopReason() override; - - StructuredData::ArraySP GetStackFrames() override; - - StructuredData::DictionarySP GetRegisterInfo() override; - - std::optional GetRegisterContext() override; - - StructuredData::ArraySP GetExtendedInfo() override; -}; -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H -- cgit v1.3