https://github.com/medismailben created https://github.com/llvm/llvm-project/pull/161870
None >From c1792fcf350dae422b1671ba18e2b095e45863e1 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <[email protected]> Date: Fri, 3 Oct 2025 16:53:37 +0100 Subject: [PATCH] [lldb] Introduce ScritedFrameProvider Signed-off-by: Med Ismail Bennani <[email protected]> --- lldb/include/lldb/API/SBThread.h | 2 + .../ScriptedFrameProviderInterface.h | 27 ++++++ .../lldb/Interpreter/ScriptInterpreter.h | 5 + .../lldb/Interpreter/ScriptedFrameProvider.h | 51 ++++++++++ lldb/include/lldb/Target/Thread.h | 9 ++ lldb/include/lldb/lldb-forward.h | 6 ++ lldb/source/API/SBThread.cpp | 27 ++++++ lldb/source/Commands/CommandObjectFrame.cpp | 95 +++++++++++++++++++ lldb/source/Commands/CommandObjectThread.cpp | 1 + lldb/source/Interpreter/CMakeLists.txt | 1 + .../Interpreter/ScriptedFrameProvider.cpp | 86 +++++++++++++++++ .../Python/Interfaces/CMakeLists.txt | 1 + .../ScriptInterpreterPythonInterfaces.h | 1 + .../ScriptedFrameProviderPythonInterface.cpp | 57 +++++++++++ .../ScriptedFrameProviderPythonInterface.h | 41 ++++++++ .../Interfaces/ScriptedPythonInterface.h | 4 + .../Python/ScriptInterpreterPython.cpp | 5 + .../Python/ScriptInterpreterPythonImpl.h | 3 + lldb/source/Target/Thread.cpp | 30 ++++++ 19 files changed, 452 insertions(+) create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h create mode 100644 lldb/include/lldb/Interpreter/ScriptedFrameProvider.h create mode 100644 lldb/source/Interpreter/ScriptedFrameProvider.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index e9fe5858d125e..7b91228528bc7 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -229,6 +229,8 @@ class LLDB_API SBThread { SBValue GetSiginfo(); + void RegisterFrameProvider(const char *class_name, SBStructuredData &args_data); + private: friend class SBBreakpoint; friend class SBBreakpointLocation; diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h new file mode 100644 index 0000000000000..7618d5e15d563 --- /dev/null +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h @@ -0,0 +1,27 @@ +//===-- ScriptedFrameProviderInterface.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEPROVIDERINTERFACE_H +#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEPROVIDERINTERFACE_H + +#include "lldb/lldb-private.h" + +#include "ScriptedInterface.h" + +namespace lldb_private { +class ScriptedFrameProviderInterface : public ScriptedInterface { +public: + virtual llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, lldb::ThreadSP thread_sp, + StructuredData::DictionarySP args_sp) = 0; + + virtual StructuredData::ArraySP GetStackFrames() { return {}; } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEPROVIDERINTERFACE_H diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 024bbc90a9a39..76ade002089bb 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -27,6 +27,7 @@ #include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" @@ -536,6 +537,10 @@ class ScriptInterpreter : public PluginInterface { return {}; } + virtual lldb::ScriptedFrameProviderInterfaceSP CreateScriptedFrameProviderInterface() { + return {}; + } + virtual lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() { return {}; diff --git a/lldb/include/lldb/Interpreter/ScriptedFrameProvider.h b/lldb/include/lldb/Interpreter/ScriptedFrameProvider.h new file mode 100644 index 0000000000000..6c4053f11eeb3 --- /dev/null +++ b/lldb/include/lldb/Interpreter/ScriptedFrameProvider.h @@ -0,0 +1,51 @@ +//===-- ScriptedFrameProvider.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_SCRIPTEDFRAMEPROVIDER_H +#define LLDB_INTERPRETER_SCRIPTEDFRAMEPROVIDER_H + +#include "lldb/Utility/ScriptedMetadata.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-forward.h" +#include "llvm/Support/Error.h" + +namespace lldb_private { + +class ScriptedFrameProvider { +public: + /// Constructor that initializes the scripted frame provider. + /// + /// \param[in] thread_sp + /// The thread for which to provide scripted frames. + /// + /// \param[in] scripted_metadata + /// The metadata containing the class name and arguments for the + /// scripted frame provider. + /// + /// \param[out] error + /// Status object to report any errors during initialization. + ScriptedFrameProvider(lldb::ThreadSP thread_sp, + const ScriptedMetadata &scripted_metadata, + Status &error); + ~ScriptedFrameProvider(); + + /// Get the stack frames from the scripted frame provider. + /// + /// \return + /// An Expected containing the StackFrameListSP if successful, + /// otherwise an error describing what went wrong. + llvm::Expected<lldb::StackFrameListSP> GetStackFrames(); + +private: + lldb::ThreadSP m_thread_sp; + lldb::ScriptedFrameProviderInterfaceSP m_interface_sp; +}; + +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_SCRIPTEDFRAMEPROVIDER_H diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 688c056da2633..d0c33f557b12b 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -1294,6 +1294,10 @@ class Thread : public std::enable_shared_from_this<Thread>, /// The PC value before execution was resumed. May not be available; /// an empty std::optional is returned in that case. std::optional<lldb::addr_t> GetPreviousFrameZeroPC(); + + void SetScriptedFrameProvider(const ScriptedMetadata &scripted_metadata); + + void ClearScriptedFrameProvider(); protected: friend class ThreadPlan; @@ -1338,6 +1342,8 @@ class Thread : public std::enable_shared_from_this<Thread>, lldb::StackFrameListSP GetStackFrameList(); + llvm::Expected<lldb::StackFrameListSP> GetScriptedFrameList(); + void SetTemporaryResumeState(lldb::StateType new_state) { m_temporary_resume_state = new_state; } @@ -1400,6 +1406,9 @@ class Thread : public std::enable_shared_from_this<Thread>, /// The Thread backed by this thread, if any. lldb::ThreadWP m_backed_thread; + /// The Scripted Frame Provider, if any. + lldb::ScriptedFrameProviderSP m_frame_provider_sp; + private: bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info // for this thread? diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index af5656b3dcad1..85045a803b07a 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -188,6 +188,8 @@ class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; class ScriptedFrameInterface; +class ScriptedFrameProvider; +class ScriptedFrameProviderInterface; class ScriptedMetadata; class ScriptedBreakpointInterface; class ScriptedPlatformInterface; @@ -411,6 +413,10 @@ typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP; typedef std::shared_ptr<lldb_private::ScriptedFrameInterface> ScriptedFrameInterfaceSP; +typedef std::shared_ptr<lldb_private::ScriptedFrameProvider> + ScriptedFrameProviderSP; +typedef std::shared_ptr<lldb_private::ScriptedFrameProviderInterface> + ScriptedFrameProviderInterfaceSP; typedef std::shared_ptr<lldb_private::ScriptedMetadata> ScriptedMetadataSP; typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface> ScriptedPlatformInterfaceUP; diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 4e4aa48bc9a2e..a18d540f2a017 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -39,6 +39,7 @@ #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepRange.h" #include "lldb/Utility/Instrumentation.h" +#include "lldb/Utility/ScriptedMetadata.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StructuredData.h" @@ -1324,3 +1325,29 @@ SBValue SBThread::GetSiginfo() { return SBValue(); return thread_sp->GetSiginfoValue(); } + +void SBThread::RegisterFrameProvider(const char *class_name, + SBStructuredData &dict) { + LLDB_INSTRUMENT_VA(this, class_name, args_data); + + ThreadSP thread_sp = m_opaque_sp->GetThreadSP(); + if (!thread_sp) + return; + + if (!dict.IsValid() || !dict.m_impl_up) + return; + + StructuredData::ObjectSP obj_sp = dict.m_impl_up->GetObjectSP(); + + if (!obj_sp) + return; + + StructuredData::DictionarySP dict_sp = + std::make_shared<StructuredData::Dictionary>(obj_sp); + if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) + return; + + + ScriptedMetadata metadata(class_name, dict_sp); + thread_sp->SetScriptedFrameProvider(metadata); +} diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 88a02dce35b9d..02d62aa9249d1 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Interpreter/Options.h" @@ -29,6 +30,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/ScriptedMetadata.h" #include "lldb/ValueObject/ValueObject.h" #include <memory> @@ -1223,6 +1225,97 @@ class CommandObjectFrameRecognizer : public CommandObjectMultiword { ~CommandObjectFrameRecognizer() override = default; }; +#pragma mark CommandObjectFrameProvider + +#define LLDB_OPTIONS_frame_provider_register +#include "CommandOptions.inc" + +class CommandObjectFrameProviderRegister : public CommandObjectParsed { +public: + CommandObjectFrameProviderRegister(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "frame provider register", + "Register frame provider into current thread.", + nullptr, eCommandRequiresThread), + + m_class_options("frame provider", true, 'C', 'k', 'v', 0) { + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_ALL); + m_all_options.Finalize(); + + AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatOptional); + } + + ~CommandObjectFrameProviderRegister() override = default; + + Options *GetOptions() override { return &m_all_options; } + + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + // No repeat for "process launch"... + return std::string(""); + } + +protected: + void DoExecute(Args &launch_args, CommandReturnObject &result) override { + ScriptedMetadata metadata(m_class_options.GetName(), m_class_options.GetStructuredData()); + + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (!thread) { + result.AppendError("invalid thread"); + return; + } + + thread->SetScriptedFrameProvider(metadata); + result.SetStatus(eReturnStatusSuccessFinishResult); + result.AppendMessageWithFormat( + "Successfully registered scripted frame provider '%s'\n", + m_class_options.GetName().c_str()); + } + + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; +}; + +class CommandObjectFrameProviderClear : public CommandObjectParsed { +public: + CommandObjectFrameProviderClear(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "frame provider clear", + "Delete registered frame provider.", nullptr) {} + + ~CommandObjectFrameProviderClear() override = default; + +protected: + void DoExecute(Args &command, CommandReturnObject &result) override { + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (!thread) { + result.AppendError("invalid thread"); + return; + } + + thread->ClearScriptedFrameProvider(); + + result.SetStatus(eReturnStatusSuccessFinishResult); + } +}; + +class CommandObjectFrameProvider : public CommandObjectMultiword { +public: + CommandObjectFrameProvider(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "frame provider", + "Commands for registering and viewing frame providers.", + "frame provider [<sub-command-options>] ") { + LoadSubCommand("register", CommandObjectSP(new CommandObjectFrameProviderRegister( + interpreter))); + LoadSubCommand( + "clear", + CommandObjectSP(new CommandObjectFrameProviderClear(interpreter))); + } + + ~CommandObjectFrameProvider() override = default; +}; + #pragma mark CommandObjectMultiwordFrame // CommandObjectMultiwordFrame @@ -1243,6 +1336,8 @@ CommandObjectMultiwordFrame::CommandObjectMultiwordFrame( LoadSubCommand("variable", CommandObjectSP(new CommandObjectFrameVariable(interpreter))); #if LLDB_ENABLE_PYTHON + LoadSubCommand("provider", CommandObjectSP(new CommandObjectFrameProvider( + interpreter))); LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer( interpreter))); #endif diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index bbec714642ec9..0092151a13dd8 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -35,6 +35,7 @@ #include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Target/Trace.h" #include "lldb/Target/TraceDumper.h" +#include "lldb/Utility/ScriptedMetadata.h" #include "lldb/Utility/State.h" #include "lldb/ValueObject/ValueObject.h" diff --git a/lldb/source/Interpreter/CMakeLists.txt b/lldb/source/Interpreter/CMakeLists.txt index 8af7373702c38..ab877ddeecba8 100644 --- a/lldb/source/Interpreter/CMakeLists.txt +++ b/lldb/source/Interpreter/CMakeLists.txt @@ -53,6 +53,7 @@ add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES OptionGroupWatchpoint.cpp Options.cpp Property.cpp + ScriptedFrameProvider.cpp ScriptInterpreter.cpp ADDITIONAL_HEADER_DIRS diff --git a/lldb/source/Interpreter/ScriptedFrameProvider.cpp b/lldb/source/Interpreter/ScriptedFrameProvider.cpp new file mode 100644 index 0000000000000..b35ed5d20f6ba --- /dev/null +++ b/lldb/source/Interpreter/ScriptedFrameProvider.cpp @@ -0,0 +1,86 @@ +//===-- ScriptedFrameProvider.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/Interpreter/ScriptedFrameProvider.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ScriptedMetadata.h" +#include "lldb/Utility/Status.h" +#include "llvm/Support/Error.h" + +using namespace lldb; +using namespace lldb_private; + +ScriptedFrameProvider::ScriptedFrameProvider( + ThreadSP thread_sp, const ScriptedMetadata &scripted_metadata, + Status &error) + : m_thread_sp(thread_sp), m_interface_sp(nullptr) { + if (!m_thread_sp) { + error = Status::FromErrorString( + "cannot create scripted frame provider: Invalid thread"); + return; + } + + ProcessSP process_sp = m_thread_sp->GetProcess(); + if (!process_sp) { + error = Status::FromErrorString( + "cannot create scripted frame provider: Invalid process"); + return; + } + + ScriptInterpreter *script_interp = + process_sp->GetTarget().GetDebugger().GetScriptInterpreter(); + if (!script_interp) { + error = Status::FromErrorString("cannot create scripted frame provider: No " + "script interpreter installed"); + return; + } + + m_interface_sp = script_interp->CreateScriptedFrameProviderInterface(); + if (!m_interface_sp) { + error = Status::FromErrorString( + "cannot create scripted frame provider: Script interpreter couldn't " + "create Scripted Frame Provider Interface"); + return; + } + + auto obj_or_err = m_interface_sp->CreatePluginObject( + scripted_metadata.GetClassName(), m_thread_sp, + scripted_metadata.GetArgsSP()); + if (!obj_or_err) { + error = Status::FromError(obj_or_err.takeError()); + return; + } + + StructuredData::ObjectSP object_sp = *obj_or_err; + if (!object_sp || !object_sp->IsValid()) { + error = Status::FromErrorString( + "cannot create scripted frame provider: Failed to create valid script " + "object"); + return; + } + + error.Clear(); +} + +ScriptedFrameProvider::~ScriptedFrameProvider() = default; + +llvm::Expected<StackFrameListSP> ScriptedFrameProvider::GetStackFrames() { + if (!m_interface_sp) + return llvm::createStringError( + "cannot get stack frames: Scripted frame provider not initialized"); + + auto frames = m_interface_sp->GetStackFrames(); + + // TODO: Convert StructuredData::ArraySP to StackFrameListSP + // This is a placeholder for now + return nullptr; +} \ No newline at end of file diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index 09103573b89c5..50569cdefaafa 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt @@ -23,6 +23,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN OperatingSystemPythonInterface.cpp ScriptInterpreterPythonInterfaces.cpp ScriptedFramePythonInterface.cpp + ScriptedFrameProviderPythonInterface.cpp ScriptedPlatformPythonInterface.cpp ScriptedProcessPythonInterface.cpp ScriptedPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h index 3814f46615078..0b9c7eb107bf5 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h @@ -18,6 +18,7 @@ #include "OperatingSystemPythonInterface.h" #include "ScriptedBreakpointPythonInterface.h" #include "ScriptedFramePythonInterface.h" +#include "ScriptedFrameProviderPythonInterface.h" #include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedStopHookPythonInterface.h" diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp new file mode 100644 index 0000000000000..b9a659c44e6f1 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp @@ -0,0 +1,57 @@ +//===-- ScriptedFrameProviderPythonInterface.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/Thread.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 "ScriptedFrameProviderPythonInterface.h" +#include <optional> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedFrameProviderPythonInterface::ScriptedFrameProviderPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedFrameProviderInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected<StructuredData::GenericSP> +ScriptedFrameProviderPythonInterface::CreatePluginObject( + const llvm::StringRef class_name, lldb::ThreadSP thread_sp, + StructuredData::DictionarySP args_sp) { + if (!thread_sp) + return llvm::createStringError("Invalid thread"); + + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + thread_sp, sd_impl); +} + +StructuredData::ArraySP ScriptedFrameProviderPythonInterface::GetStackFrames() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_stackframes", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h new file mode 100644 index 0000000000000..202769c094f06 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h @@ -0,0 +1,41 @@ +//===-- ScriptedFrameProviderPythonInterface.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_SCRIPTEDFRAMEPROVIDERPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDFRAMEPROVIDERPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h" +#include <optional> + +namespace lldb_private { +class ScriptedFrameProviderPythonInterface + : public ScriptedFrameProviderInterface, + public ScriptedPythonInterface { +public: + ScriptedFrameProviderPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, lldb::ThreadSP thread_sp, + StructuredData::DictionarySP args_sp) override; + + llvm::SmallVector<AbstractMethodRequirement> + GetAbstractMethodRequirements() const override { + return llvm::SmallVector<AbstractMethodRequirement>({{"get_stackframes"}}); + } + + StructuredData::ArraySP GetStackFrames() override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDFRAMEPROVIDERPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index f769d3d29add7..7f7446cc00423 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -439,6 +439,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { python::PythonObject Transform(lldb::ProcessSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg); } + + python::PythonObject Transform(lldb::ThreadSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } python::PythonObject Transform(lldb::ThreadPlanSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 73c5c72932ff1..9ef5ac4acb6a3 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1526,6 +1526,11 @@ ScriptInterpreterPythonImpl::CreateScriptedFrameInterface() { return std::make_shared<ScriptedFramePythonInterface>(*this); } +ScriptedFrameProviderInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedFrameProviderInterface() { + return std::make_shared<ScriptedFrameProviderPythonInterface>(*this); +} + ScriptedThreadPlanInterfaceSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() { return std::make_shared<ScriptedThreadPlanPythonInterface>(*this); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index dedac280788f4..0dd5ae52c8955 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -101,6 +101,9 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override; + lldb::ScriptedFrameProviderInterfaceSP + CreateScriptedFrameProviderInterface() override; + lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override; diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 8c3e19725f8cb..acf126a548691 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -13,9 +13,13 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Host/Host.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" +#include "lldb/Interpreter/ScriptedFrameProvider.h" +#include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Symbol/Function.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" @@ -45,6 +49,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/ScriptedMetadata.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" @@ -1446,6 +1451,31 @@ StackFrameListSP Thread::GetStackFrameList() { return m_curr_frames_sp; } +llvm::Expected<StackFrameListSP> Thread::GetScriptedFrameList() { + std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); + + if (!m_frame_provider_sp) + return llvm::createStringError("No scripted frame provider has been set"); + + return m_frame_provider_sp->GetStackFrames(); +} + +void Thread::SetScriptedFrameProvider(const ScriptedMetadata &scripted_metadata) { + std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); + + Status error; + m_frame_provider_sp = std::make_shared<ScriptedFrameProvider>( + shared_from_this(), scripted_metadata, error); + + if (error.Fail()) + m_frame_provider_sp.reset(); +} + +void Thread::ClearScriptedFrameProvider() { + std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); + m_frame_provider_sp.reset(); +} + std::optional<addr_t> Thread::GetPreviousFrameZeroPC() { return m_prev_framezero_pc; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
