diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces')
10 files changed, 1339 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..9ba4731032bd --- /dev/null +++ b/contrib/llvm-project/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<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..e86b34d6b930 --- /dev/null +++ b/contrib/llvm-project/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 <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 (!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 (!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<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 (!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 (!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<std::string> +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<StructuredData::DictionarySP>("get_process_metadata", error); + +  if (!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..6f22503b279c --- /dev/null +++ b/contrib/llvm-project/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 <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); +  else +    error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); + +  return {}; +} + +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..163659234466 --- /dev/null +++ b/contrib/llvm-project/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 <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: %s", +                                          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 ErrorWithMessage<T>(caller_signature, +                                 "Python implementor not allocated.", error); + +    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::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 <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 <> +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/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp new file mode 100644 index 000000000000..18e268527eb2 --- /dev/null +++ b/contrib/llvm-project/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 <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 (!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 (!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<StateType>(obj->GetUnsignedIntegerValue(eStateInvalid)); +} + +std::optional<std::string> 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<StructuredData::DictionarySP>("get_stop_reason", error); + +  if (!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 (!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 (!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 (!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 (!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 | 
