Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lldb/bindings/python/static-binding/LLDBWrapPython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77543,12 +77543,12 @@ SWIGINTERN PyObject *_wrap_SBThread_GetFrames(PyObject *self, PyObject *args) {
swig_obj[0] = args;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_lldb__SBThread, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBThread_GetFrames" "', argument " "1"" of type '" "lldb::SBThread *""'");
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBThread_GetFrames" "', argument " "1"" of type '" "lldb::SBThread const *""'");
}
arg1 = reinterpret_cast< lldb::SBThread * >(argp1);
{
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
result = (arg1)->GetFrames();
result = ((lldb::SBThread const *)arg1)->GetFrames();
SWIG_PYTHON_THREAD_END_ALLOW;
}
resultobj = SWIG_NewPointerObj((new lldb::SBFrameList(result)), SWIGTYPE_p_lldb__SBFrameList, SWIG_POINTER_OWN | 0 );
Expand Down
28 changes: 28 additions & 0 deletions lldb/examples/python/templates/scripted_frame_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,34 @@ def get_description(self):
"""
pass

@staticmethod
def get_priority():
"""Get the priority of this frame provider.

This static method is called to determine the evaluation order when
multiple frame providers could apply to the same thread. Lower numbers
indicate higher priority (like Unix nice values).

Returns:
int or None: Priority value where 0 is highest priority.
Return None for default priority (UINT32_MAX - lowest priority).

Example:

.. code-block:: python

@staticmethod
def get_priority():
# High priority - runs before most providers
return 10

@staticmethod
def get_priority():
# Default priority - runs last
return None
"""
return None # Default/lowest priority

def __init__(self, input_frames, args):
"""Construct a scripted frame provider.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ class ScriptedFrameProviderInterface : public ScriptedInterface {
/// empty string if no description is available.
virtual std::string GetDescription(llvm::StringRef class_name) { return {}; }

/// Get the priority of this frame provider.
///
/// This is called by the descriptor to fetch the priority from the
/// scripted implementation. Implementations should call a static method
/// on the scripting class to retrieve the priority. Lower numbers indicate
/// higher priority (like Unix nice values).
///
/// \param class_name The name of the scripting class implementing the
/// provider.
///
/// \return Priority value where 0 is highest priority, or std::nullopt for
/// default priority (UINT32_MAX - lowest priority).
virtual std::optional<uint32_t> GetPriority(llvm::StringRef class_name) {
return std::nullopt;
}

virtual StructuredData::ObjectSP GetFrameAtIndex(uint32_t index) {
return {};
}
Expand Down
6 changes: 5 additions & 1 deletion lldb/include/lldb/Target/StackFrameList.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ class SyntheticStackFrameList : public StackFrameList {
public:
SyntheticStackFrameList(Thread &thread, lldb::StackFrameListSP input_frames,
const lldb::StackFrameListSP &prev_frames_sp,
bool show_inline_frames);
bool show_inline_frames,
lldb::SyntheticFrameProviderSP provider_sp);

protected:
/// Override FetchFramesUpTo to lazily return frames from the provider
Expand All @@ -250,6 +251,9 @@ class SyntheticStackFrameList : public StackFrameList {
/// The input stack frame list that the provider transforms.
/// This could be a real StackFrameList or another SyntheticStackFrameList.
lldb::StackFrameListSP m_input_frames;

/// The provider that transforms the input frames.
lldb::SyntheticFrameProviderSP m_provider;
};

} // namespace lldb_private
Expand Down
21 changes: 21 additions & 0 deletions lldb/include/lldb/Target/SyntheticFrameProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ struct ScriptedFrameProviderDescriptor {
/// empty string if no description is available.
std::string GetDescription() const;

/// Get the priority of this frame provider.
///
/// Priority determines the order in which providers are evaluated when
/// multiple providers could apply to the same thread. Lower numbers indicate
/// higher priority (like Unix nice values).
///
/// \return Priority value where 0 is highest priority, or std::nullopt for
/// default priority (UINT32_MAX - lowest priority).
std::optional<uint32_t> GetPriority() const;

/// Check if this descriptor applies to the given thread.
bool AppliesToThread(Thread &thread) const {
// If no thread specs specified, applies to all threads.
Expand Down Expand Up @@ -143,6 +153,17 @@ class SyntheticFrameProvider : public PluginInterface {

virtual std::string GetDescription() const = 0;

/// Get the priority of this frame provider.
///
/// Priority determines the order in which providers are evaluated when
/// multiple providers could apply to the same thread. Lower numbers indicate
/// higher priority (like Unix nice values).
///
/// \return
/// Priority value where 0 is highest priority, or std::nullopt for
/// default priority (UINT32_MAX - lowest priority).
virtual std::optional<uint32_t> GetPriority() const { return std::nullopt; }

/// Get a single stack frame at the specified index.
///
/// This method is called lazily - frames are only created when requested.
Expand Down
9 changes: 5 additions & 4 deletions lldb/include/lldb/Target/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -1334,8 +1334,9 @@ class Thread : public std::enable_shared_from_this<Thread>,

void ClearScriptedFrameProvider();

lldb::SyntheticFrameProviderSP GetFrameProvider() const {
return m_frame_provider_sp;
const llvm::SmallVector<lldb::SyntheticFrameProviderSP, 0> &
GetFrameProviders() const {
return m_frame_providers;
}

protected:
Expand Down Expand Up @@ -1441,8 +1442,8 @@ 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::SyntheticFrameProviderSP m_frame_provider_sp;
/// The Scripted Frame Providers for this thread.
llvm::SmallVector<lldb::SyntheticFrameProviderSP, 0> m_frame_providers;

private:
bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Core/CoreProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ let Definition = "debugger" in {
Desc<"The default disassembly format string to use when disassembling instruction sequences.">;
def FrameFormat: Property<"frame-format", "FormatEntity">,
Global,
DefaultStringValue<"frame #${frame.index}: {${ansi.fg.cyan}${frame.pc}${ansi.normal}}{ ${module.file.basename}{`}}{${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
DefaultStringValue<"frame #${frame.index}: {${ansi.fg.cyan}${frame.pc}${ansi.normal} }{${module.file.basename}{`}}{${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
Desc<"The default frame format string to use when displaying stack frame information for threads.">;
def NotiftVoid: Property<"notify-void", "Boolean">,
Global,
Expand Down Expand Up @@ -316,7 +316,7 @@ let Definition = "debugger" in {
Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">;
def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">,
Global,
DefaultStringValue<"frame #${frame.index}: {${ansi.fg.cyan}${frame.pc}${ansi.normal}}{ ${module.file.basename}{`}}{${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
DefaultStringValue<"frame #${frame.index}: {${ansi.fg.cyan}${frame.pc}${ansi.normal} }{${module.file.basename}{`}}{${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">,
Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">;
def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
Global,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ std::string ScriptedFrameProviderPythonInterface::GetDescription(
return obj->GetStringValue().str();
}

std::optional<uint32_t>
ScriptedFrameProviderPythonInterface::GetPriority(llvm::StringRef class_name) {
Status error;
StructuredData::ObjectSP obj =
CallStaticMethod(class_name, "get_priority", error);

if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
error))
return std::nullopt;

// Try to extract as unsigned integer. Return nullopt if Python returned None
// or if extraction fails.
if (StructuredData::UnsignedInteger *int_obj = obj->GetAsUnsignedInteger())
return static_cast<uint32_t>(int_obj->GetValue());

return std::nullopt;
}

StructuredData::ObjectSP
ScriptedFrameProviderPythonInterface::GetFrameAtIndex(uint32_t index) {
Status error;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class ScriptedFrameProviderPythonInterface

std::string GetDescription(llvm::StringRef class_name) override;

std::optional<uint32_t> GetPriority(llvm::StringRef class_name) override;

StructuredData::ObjectSP GetFrameAtIndex(uint32_t index) override;

static void Initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ std::string ScriptedFrameProvider::GetDescription() const {
return m_interface_sp->GetDescription(m_descriptor.GetName());
}

std::optional<uint32_t> ScriptedFrameProvider::GetPriority() const {
if (!m_interface_sp)
return std::nullopt;

return m_interface_sp->GetPriority(m_descriptor.GetName());
}

llvm::Expected<StackFrameSP>
ScriptedFrameProvider::GetFrameAtIndex(uint32_t idx) {
if (!m_interface_sp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class ScriptedFrameProvider : public SyntheticFrameProvider {

std::string GetDescription() const override;

std::optional<uint32_t> GetPriority() const override;

/// Get a single stack frame at the specified index.
llvm::Expected<lldb::StackFrameSP> GetFrameAtIndex(uint32_t idx) override;

Expand Down
13 changes: 7 additions & 6 deletions lldb/source/Target/StackFrameList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,24 @@ StackFrameList::~StackFrameList() {

SyntheticStackFrameList::SyntheticStackFrameList(
Thread &thread, lldb::StackFrameListSP input_frames,
const lldb::StackFrameListSP &prev_frames_sp, bool show_inline_frames)
const lldb::StackFrameListSP &prev_frames_sp, bool show_inline_frames,
lldb::SyntheticFrameProviderSP provider_sp)
: StackFrameList(thread, prev_frames_sp, show_inline_frames),
m_input_frames(std::move(input_frames)) {}
m_input_frames(std::move(input_frames)),
m_provider(std::move(provider_sp)) {}

bool SyntheticStackFrameList::FetchFramesUpTo(
uint32_t end_idx, InterruptionControl allow_interrupt) {

size_t num_synthetic_frames = 0;
// Check if the thread has a synthetic frame provider.
if (auto provider_sp = m_thread.GetFrameProvider()) {
// Use the synthetic frame provider to generate frames lazily.
// Use the provider to generate frames lazily.
if (m_provider) {
// Keep fetching until we reach end_idx or the provider returns an error.
for (uint32_t idx = m_frames.size(); idx <= end_idx; idx++) {
if (allow_interrupt &&
m_thread.GetProcess()->GetTarget().GetDebugger().InterruptRequested())
return true;
auto frame_or_err = provider_sp->GetFrameAtIndex(idx);
auto frame_or_err = m_provider->GetFrameAtIndex(idx);
if (!frame_or_err) {
// Provider returned error - we've reached the end.
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), frame_or_err.takeError(),
Expand Down
14 changes: 14 additions & 0 deletions lldb/source/Target/SyntheticFrameProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ void ScriptedFrameProviderDescriptor::Dump(Stream *s) const {
if (!description.empty())
s->Printf(" Description: %s\n", description.c_str());

// Show priority information.
std::optional<uint32_t> priority = GetPriority();
if (priority.has_value())
s->Printf(" Priority: %u\n", *priority);
else
s->PutCString(" Priority: Default (no priority specified)\n");

// Show thread filter information.
if (thread_specs.empty()) {
s->PutCString(" Thread Filter: (applies to all threads)\n");
Expand Down Expand Up @@ -62,6 +69,13 @@ std::string ScriptedFrameProviderDescriptor::GetDescription() const {
return {};
}

std::optional<uint32_t> ScriptedFrameProviderDescriptor::GetPriority() const {
// If we have an interface, call get_priority() to fetch it.
if (interface_sp && scripted_metadata_sp)
return interface_sp->GetPriority(scripted_metadata_sp->GetClassName());
return std::nullopt;
}

llvm::Expected<SyntheticFrameProviderSP> SyntheticFrameProvider::CreateInstance(
StackFrameListSP input_frames,
const ScriptedFrameProviderDescriptor &descriptor) {
Expand Down
Loading