diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces')
12 files changed, 1559 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp new file mode 100644 index 000000000000..c162c7367c65 --- /dev/null +++ b/contrib/llvm-project/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<StructuredData::GenericSP> +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<StructuredData::DictionarySP>( + "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<StructuredData::ArraySP>("get_thread_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +StructuredData::DictionarySP OperatingSystemPythonInterface::GetRegisterInfo() { + return ScriptedThreadPythonInterface::GetRegisterInfo(); +} + +std::optional<std::string> +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/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h new file mode 100644 index 000000000000..da7bbf13b1d5 --- /dev/null +++ b/contrib/llvm-project/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 <optional> + +namespace lldb_private { +class OperatingSystemPythonInterface + : virtual public OperatingSystemInterface, + virtual public ScriptedThreadPythonInterface { +public: + OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>({"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<std::string> GetRegisterContextForTID(lldb::tid_t tid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp new file mode 100644 index 000000000000..6e93bec80056 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp @@ -0,0 +1,96 @@ +//===-- 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" + +#include "lldb/Target/ExecutionContext.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<StructuredData::GenericSP> +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<ExecutionContextRef>(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<StructuredData::DictionarySP>("list_processes", error); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + 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<StructuredData::DictionarySP>("get_process_info", error, pid); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + 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/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h new file mode 100644 index 000000000000..0842d3a00342 --- /dev/null +++ b/contrib/llvm-project/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<StructuredData::GenericSP> + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"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/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp new file mode 100644 index 000000000000..313c597ce48f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp @@ -0,0 +1,211 @@ +//===-- 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 <optional> + +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<StructuredData::GenericSP> +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<ExecutionContextRef>(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<StructuredData::DictionarySP>("get_capabilities", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +Status +ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { + lldb::ProcessAttachInfoSP attach_info_sp = + std::make_shared<ProcessAttachInfo>(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<MemoryRegionInfo> +ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( + lldb::addr_t address, Status &error) { + auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>( + "get_memory_region_containing_address", error, address); + + if (error.Fail()) { + return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION, + error.AsCString(), error); + } + + return mem_region; +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_threads_info", error); + + if (!ScriptedInterface::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 (!ScriptedInterface::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<lldb::DataExtractorSP>( + "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 (!ScriptedInterface::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<StructuredData::ArraySP>("get_loaded_images", error); + + if (!ScriptedInterface::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 (!ScriptedInterface::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 (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetBooleanValue(); +} + +std::optional<std::string> +ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); + + if (!ScriptedInterface::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<StructuredData::DictionarySP>("get_process_metadata", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h new file mode 100644 index 000000000000..c75caa9340f2 --- /dev/null +++ b/contrib/llvm-project/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 <optional> + +namespace lldb_private { +class ScriptedProcessPythonInterface : public ScriptedProcessInterface, + public ScriptedPythonInterface { +public: + ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"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<MemoryRegionInfo> + 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<std::string> 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/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp new file mode 100644 index 000000000000..699412e437a1 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -0,0 +1,159 @@ +//===-- 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 <optional> + +using namespace lldb; +using namespace lldb_private; + +ScriptedPythonInterface::ScriptedPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedInterface(), m_interpreter(interpreter) {} + +template <> +StructuredData::ArraySP +ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( + 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<Status>( + python::PythonObject &p, Status &error) { + if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>( + python::LLDBSWIGPython_CastPyObjectToSBError(p.get()))) + return m_interpreter.GetStatusFromSBError(*sb_error); + error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); + + return {}; +} + +template <> +Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>( + python::PythonObject &p, Status &error) { + if (lldb::SBEvent *sb_event = reinterpret_cast<lldb::SBEvent *>( + python::LLDBSWIGPython_CastPyObjectToSBEvent(p.get()))) + return m_interpreter.GetOpaqueTypeFromSBEvent(*sb_event); + error.SetErrorString("Couldn't cast lldb::SBEvent to lldb_private::Event."); + + return nullptr; +} + +template <> +lldb::StreamSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>( + python::PythonObject &p, Status &error) { + if (lldb::SBStream *sb_stream = reinterpret_cast<lldb::SBStream *>( + python::LLDBSWIGPython_CastPyObjectToSBStream(p.get()))) + return m_interpreter.GetOpaqueTypeFromSBStream(*sb_stream); + error.SetErrorString("Couldn't cast lldb::SBStream to lldb_private::Stream."); + + return nullptr; +} + +template <> +lldb::DataExtractorSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( + python::PythonObject &p, Status &error) { + lldb::SBData *sb_data = reinterpret_cast<lldb::SBData *>( + 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<lldb::BreakpointSP>( + python::PythonObject &p, Status &error) { + lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast<lldb::SBBreakpoint *>( + 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<lldb::SBAttachInfo *>( + 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<lldb::SBLaunchInfo *>( + 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<MemoryRegionInfo> +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { + + lldb::SBMemoryRegionInfo *sb_mem_reg_info = + reinterpret_cast<lldb::SBMemoryRegionInfo *>( + 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/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h new file mode 100644 index 000000000000..e1a3156d10af --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -0,0 +1,480 @@ +//===-- 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 <optional> +#include <sstream> +#include <tuple> +#include <type_traits> +#include <utility> + +#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<std::map<llvm::StringLiteral, AbstractMethodCheckerCases>> + CheckAbstractMethodImplementation( + const python::PythonDictionary &class_dict) const { + + using namespace python; + + std::map<llvm::StringLiteral, AbstractMethodCheckerCases> 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 <typename... Args> + llvm::Expected<StructuredData::GenericSP> + 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<PyObject *>(script_obj->GetValue())); + } else { + auto dict = + PythonModule::MainModule().ResolveName<python::PythonDictionary>( + m_interpreter.GetDictionaryName()); + if (!dict.IsAllocated()) + return create_error( + llvm::formatv("Could not find interpreter dictionary: %s", + m_interpreter.GetDictionaryName())); + + auto init = + PythonObject::ResolveNameWithDictionary<python::PythonCallable>( + class_name, dict); + if (!init.IsAllocated()) + return create_error(llvm::formatv("Could not find script class: {0}", + class_name.data())); + + std::tuple<Args...> original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + std::string error_string; + llvm::Expected<PythonCallable::ArgInfo> 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<PythonObject> expected_return_object = + create_error("Resulting object is not initialized."); + + std::apply( + [&init, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = init(args...); + }, + transformed_args); + + 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<PythonString>(); + + 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<PythonCallable>(); + 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<PythonDictionary>(); + 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 <typename T = StructuredData::ObjectSP> + T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { + return p.CreateStructuredObject(); + } + + template <typename T = StructuredData::ObjectSP, typename... Args> + 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<T>(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 llvm::is_contained(GetAbstractMethods(), method_name) + ? ErrorWithMessage<T>(caller_signature, + "Python implementor not allocated.", + error) + : T{}; + + std::tuple<Args...> original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + llvm::Expected<PythonObject> expected_return_object = + llvm::make_error<llvm::StringError>("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<T>(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<T>( + caller_signature, + "Couldn't re-assign reference and pointer arguments.", error); + + if (!py_return.IsAllocated()) + return {}; + return ExtractValueFromPythonObject<T>(py_return, error); + } + + template <typename... Args> + Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { + Status error; + Dispatch<Status>(method_name, error, std::forward<Args>(args)...); + + return error; + } + + template <typename T> 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::ThreadPlanSP 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(Event *arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::StreamSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg.get()); + } + + python::PythonObject Transform(lldb::DataExtractorSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + template <typename T, typename U> + void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { + // If U is not a PythonObject, don't touch it! + return; + } + + template <typename T> + void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, + Status &error) { + original_arg = ExtractValueFromPythonObject<T>(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 <std::size_t... I, typename... Args> + auto TransformTuple(const std::tuple<Args...> &args, + std::index_sequence<I...>) { + return std::make_tuple(Transform(std::get<I>(args))...); + } + + // This will iterate over the Dispatch parameter pack and replace in-place + // every `lldb_private` argument that has a SB counterpart. + template <typename... Args> + auto TransformArgs(const std::tuple<Args...> &args) { + return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); + } + + template <typename T, typename U> + void TransformBack(T &original_arg, U transformed_arg, Status &error) { + ReverseTransform(original_arg, transformed_arg, error); + } + + template <std::size_t... I, typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args, + std::index_sequence<I...>) { + Status error; + (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), + error), + ...); + return error.Success(); + } + + template <typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args) { + if (sizeof...(Ts) != sizeof...(Us)) + return false; + + return ReassignPtrsOrRefsArgs(original_args, transformed_args, + std::make_index_sequence<sizeof...(Ts)>()); + } + + template <typename T, typename... Args> + void FormatArgs(std::string &fmt, T arg, Args... args) const { + FormatArgs(fmt, arg); + FormatArgs(fmt, args...); + } + + template <typename T> void FormatArgs(std::string &fmt, T arg) const { + fmt += python::PythonFormat<T>::format; + } + + void FormatArgs(std::string &fmt) const {} + + // The lifetime is managed by the ScriptInterpreter + ScriptInterpreterPythonImpl &m_interpreter; +}; + +template <> +StructuredData::ArraySP +ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( + python::PythonObject &p, Status &error); + +template <> +StructuredData::DictionarySP +ScriptedPythonInterface::ExtractValueFromPythonObject< + StructuredData::DictionarySP>(python::PythonObject &p, Status &error); + +template <> +Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( + python::PythonObject &p, Status &error); + +template <> +Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>( + python::PythonObject &p, Status &error); + +template <> +lldb::StreamSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>( + python::PythonObject &p, Status &error); + +template <> +lldb::BreakpointSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>( + 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<lldb::DataExtractorSP>( + python::PythonObject &p, Status &error); + +template <> +std::optional<MemoryRegionInfo> +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp new file mode 100644 index 000000000000..f23858c01277 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp @@ -0,0 +1,105 @@ +//===-- ScriptedThreadPlanPythonInterface.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 "ScriptedThreadPlanPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; + +ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected<StructuredData::GenericSP> +ScriptedThreadPlanPythonInterface::CreatePluginObject( + const llvm::StringRef class_name, lldb::ThreadPlanSP thread_plan_sp, + const StructuredDataImpl &args_sp) { + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + thread_plan_sp, args_sp); +} + +llvm::Expected<bool> +ScriptedThreadPlanPythonInterface::ExplainsStop(Event *event) { + Status error; + StructuredData::ObjectSP obj = Dispatch("explains_stop", error, event); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + if (!obj) + return false; + return error.ToError(); + } + + return obj->GetBooleanValue(); +} + +llvm::Expected<bool> +ScriptedThreadPlanPythonInterface::ShouldStop(Event *event) { + Status error; + StructuredData::ObjectSP obj = Dispatch("should_stop", error, event); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + if (!obj) + return false; + return error.ToError(); + } + + return obj->GetBooleanValue(); +} + +llvm::Expected<bool> ScriptedThreadPlanPythonInterface::IsStale() { + Status error; + StructuredData::ObjectSP obj = Dispatch("is_stale", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + if (!obj) + return false; + return error.ToError(); + } + + return obj->GetBooleanValue(); +} + +lldb::StateType ScriptedThreadPlanPythonInterface::GetRunState() { + Status error; + StructuredData::ObjectSP obj = Dispatch("should_step", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return lldb::eStateStepping; + + return static_cast<lldb::StateType>(obj->GetUnsignedIntegerValue( + static_cast<uint32_t>(lldb::eStateStepping))); +} + +llvm::Error +ScriptedThreadPlanPythonInterface::GetStopDescription(lldb::StreamSP &stream) { + Status error; + Dispatch("stop_description", error, stream); + + if (error.Fail()) + return error.ToError(); + + return llvm::Error::success(); +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h new file mode 100644 index 000000000000..6ec89b9f5925 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h @@ -0,0 +1,48 @@ +//===-- ScriptedThreadPlanPythonInterface.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_SCRIPTEDTHREADPLANPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h" +#include <optional> + +namespace lldb_private { +class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface, + public ScriptedPythonInterface { +public: + ScriptedThreadPlanPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(const llvm::StringRef class_name, + lldb::ThreadPlanSP thread_plan_sp, + const StructuredDataImpl &args_sp) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return {}; + } + + llvm::Expected<bool> ExplainsStop(Event *event) override; + + llvm::Expected<bool> ShouldStop(Event *event) override; + + llvm::Expected<bool> IsStale() override; + + lldb::StateType GetRunState() override; + + llvm::Error GetStopDescription(lldb::StreamSP &stream) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp new file mode 100644 index 000000000000..8af89d761764 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp @@ -0,0 +1,147 @@ +//===-- 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 "ScriptedThreadPythonInterface.h" +#include <optional> + +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<StructuredData::GenericSP> +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<ExecutionContextRef>(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 (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return LLDB_INVALID_THREAD_ID; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); +} + +std::optional<std::string> ScriptedThreadPythonInterface::GetName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_name", error); + + if (!ScriptedInterface::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 (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return eStateInvalid; + + return static_cast<StateType>(obj->GetUnsignedIntegerValue(eStateInvalid)); +} + +std::optional<std::string> ScriptedThreadPythonInterface::GetQueue() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_queue", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetStringValue().str(); +} + +StructuredData::DictionarySP ScriptedThreadPythonInterface::GetStopReason() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_stop_reason", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +StructuredData::ArraySP ScriptedThreadPythonInterface::GetStackFrames() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_stackframes", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_register_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +std::optional<std::string> ScriptedThreadPythonInterface::GetRegisterContext() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_register_context", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetAsString()->GetValue().str(); +} + +StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_extended_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h new file mode 100644 index 000000000000..5676f7f1d675 --- /dev/null +++ b/contrib/llvm-project/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 <optional> + +namespace lldb_private { +class ScriptedThreadPythonInterface : public ScriptedThreadInterface, + public ScriptedPythonInterface { +public: + ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"get_stop_reason", "get_register_context"}); + } + + lldb::tid_t GetThreadID() override; + + std::optional<std::string> GetName() override; + + lldb::StateType GetState() override; + + std::optional<std::string> GetQueue() override; + + StructuredData::DictionarySP GetStopReason() override; + + StructuredData::ArraySP GetStackFrames() override; + + StructuredData::DictionarySP GetRegisterInfo() override; + + std::optional<std::string> GetRegisterContext() override; + + StructuredData::ArraySP GetExtendedInfo() override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H |