diff options
Diffstat (limited to 'lldb/include/lldb/Target/SyntheticFrameProvider.h')
| -rw-r--r-- | lldb/include/lldb/Target/SyntheticFrameProvider.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/lldb/include/lldb/Target/SyntheticFrameProvider.h b/lldb/include/lldb/Target/SyntheticFrameProvider.h new file mode 100644 index 0000000..2d5330c --- /dev/null +++ b/lldb/include/lldb/Target/SyntheticFrameProvider.h @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// 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_TARGET_SYNTHETICFRAMEPROVIDER_H +#define LLDB_TARGET_SYNTHETICFRAMEPROVIDER_H + +#include "lldb/Core/PluginInterface.h" +#include "lldb/Target/StackFrameList.h" +#include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/ScriptedMetadata.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-forward.h" +#include "llvm/Support/Error.h" + +#include <optional> +#include <vector> + +namespace lldb_private { + +/// This struct contains the metadata needed to instantiate a frame provider +/// and optional filters to control which threads it applies to. +struct ScriptedFrameProviderDescriptor { + /// Metadata for instantiating the provider (e.g. script class name and args). + lldb::ScriptedMetadataSP scripted_metadata_sp; + + /// Interface for calling static methods on the provider class. + lldb::ScriptedFrameProviderInterfaceSP interface_sp; + + /// Optional list of thread specifications to which this provider applies. + /// If empty, the provider applies to all threads. A thread matches if it + /// satisfies ANY of the specs in this vector (OR logic). + std::vector<ThreadSpec> thread_specs; + + ScriptedFrameProviderDescriptor() = default; + + ScriptedFrameProviderDescriptor(lldb::ScriptedMetadataSP metadata_sp) + : scripted_metadata_sp(metadata_sp) {} + + ScriptedFrameProviderDescriptor(lldb::ScriptedMetadataSP metadata_sp, + const std::vector<ThreadSpec> &specs) + : scripted_metadata_sp(metadata_sp), thread_specs(specs) {} + + /// Get the name of this descriptor (the scripted class name). + llvm::StringRef GetName() const { + return scripted_metadata_sp ? scripted_metadata_sp->GetClassName() : ""; + } + + /// Get the description of this frame provider. + /// + /// \return A string describing what this frame provider does, or an + /// empty string if no description is available. + std::string GetDescription() const; + + /// Check if this descriptor applies to the given thread. + bool AppliesToThread(Thread &thread) const { + // If no thread specs specified, applies to all threads. + if (thread_specs.empty()) + return true; + + // Check if the thread matches any of the specs (OR logic). + for (const auto &spec : thread_specs) { + if (spec.ThreadPassesBasicTests(thread)) + return true; + } + return false; + } + + /// Check if this descriptor has valid metadata for script-based providers. + bool IsValid() const { return scripted_metadata_sp != nullptr; } + + /// Get a unique identifier for this descriptor based on its contents. + /// The ID is computed from the class name and arguments dictionary, + /// not from the pointer address, so two descriptors with the same + /// contents will have the same ID. + uint32_t GetID() const; + + /// Dump a description of this descriptor to the given stream. + void Dump(Stream *s) const; +}; + +/// Base class for all synthetic frame providers. +/// +/// Synthetic frame providers allow modifying or replacing the stack frames +/// shown for a thread. This is useful for: +/// - Providing frames for custom calling conventions or languages. +/// - Reconstructing missing frames from crash dumps or core files. +/// - Adding diagnostic or synthetic frames for debugging. +/// - Visualizing state machines or async execution contexts. +class SyntheticFrameProvider : public PluginInterface { +public: + /// Try to create a SyntheticFrameProvider instance for the given input + /// frames and descriptor. + /// + /// This method iterates through all registered SyntheticFrameProvider + /// plugins and returns the first one that can handle the given descriptor. + /// + /// \param[in] input_frames + /// The input stack frame list that this provider will transform. + /// This could be real unwound frames or output from another provider. + /// + /// \param[in] descriptor + /// The descriptor containing metadata for the provider. + /// + /// \return + /// A shared pointer to a SyntheticFrameProvider if one could be created, + /// otherwise an \a llvm::Error. + static llvm::Expected<lldb::SyntheticFrameProviderSP> + CreateInstance(lldb::StackFrameListSP input_frames, + const ScriptedFrameProviderDescriptor &descriptor); + + /// Try to create a SyntheticFrameProvider instance for the given input + /// frames using a specific C++ plugin. + /// + /// This method directly invokes a specific SyntheticFrameProvider plugin + /// by name, bypassing the descriptor-based plugin iteration. This is useful + /// for C++ plugins that don't require scripted metadata. + /// + /// \param[in] input_frames + /// The input stack frame list that this provider will transform. + /// This could be real unwound frames or output from another provider. + /// + /// \param[in] plugin_name + /// The name of the plugin to use for creating the provider. + /// + /// \param[in] thread_specs + /// Optional list of thread specifications to which this provider applies. + /// If empty, the provider applies to all threads. + /// + /// \return + /// A shared pointer to a SyntheticFrameProvider if one could be created, + /// otherwise an \a llvm::Error. + static llvm::Expected<lldb::SyntheticFrameProviderSP> + CreateInstance(lldb::StackFrameListSP input_frames, + llvm::StringRef plugin_name, + const std::vector<ThreadSpec> &thread_specs = {}); + + ~SyntheticFrameProvider() override; + + virtual std::string GetDescription() const = 0; + + /// Get a single stack frame at the specified index. + /// + /// This method is called lazily - frames are only created when requested. + /// The provider can access its input frames via GetInputFrames() if needed. + /// + /// \param[in] idx + /// The index of the frame to create. + /// + /// \return + /// An Expected containing the StackFrameSP if successful. Returns an + /// error when the index is beyond the last frame to signal the end of + /// the frame list. + virtual llvm::Expected<lldb::StackFrameSP> GetFrameAtIndex(uint32_t idx) = 0; + + /// Get the thread associated with this provider. + Thread &GetThread() { return m_input_frames->GetThread(); } + + /// Get the input frames that this provider transforms. + lldb::StackFrameListSP GetInputFrames() const { return m_input_frames; } + +protected: + SyntheticFrameProvider(lldb::StackFrameListSP input_frames); + + lldb::StackFrameListSP m_input_frames; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_SYNTHETICFRAMEPROVIDER_H |
