-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[lldb] Introduce ScriptedFrameProvider for real threads #161870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
medismailben
wants to merge
1
commit into
llvm:main
Choose a base branch
from
medismailben:scripted-frame-provider
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,442
−66
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
lldb/examples/python/templates/scripted_frame_provider.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
from abc import ABCMeta, abstractmethod | ||
|
||
import lldb | ||
|
||
|
||
class ScriptedFrameProvider(metaclass=ABCMeta): | ||
""" | ||
The base class for a scripted frame provider. | ||
|
||
A scripted frame provider allows you to provide custom stack frames for a | ||
thread, which can be used to augment or replace the standard unwinding | ||
mechanism. 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 | ||
|
||
Most of the base class methods are `@abstractmethod` that need to be | ||
overwritten by the inheriting class. | ||
|
||
Example usage: | ||
|
||
.. code-block:: python | ||
|
||
# Attach a frame provider to a thread | ||
thread = process.GetSelectedThread() | ||
error = lldb.SBError() | ||
thread.SetScriptedFrameProvider( | ||
"my_module.MyFrameProvider", | ||
lldb.SBStructuredData() | ||
) | ||
""" | ||
|
||
@abstractmethod | ||
def __init__(self, thread, args): | ||
"""Construct a scripted frame provider. | ||
|
||
Args: | ||
thread (lldb.SBThread): The thread for which to provide frames. | ||
args (lldb.SBStructuredData): A Dictionary holding arbitrary | ||
key/value pairs used by the scripted frame provider. | ||
""" | ||
self.thread = None | ||
self.args = None | ||
self.target = None | ||
self.process = None | ||
|
||
if isinstance(thread, lldb.SBThread) and thread.IsValid(): | ||
self.thread = thread | ||
self.process = thread.GetProcess() | ||
if self.process and self.process.IsValid(): | ||
self.target = self.process.GetTarget() | ||
|
||
if isinstance(args, lldb.SBStructuredData) and args.IsValid(): | ||
self.args = args | ||
|
||
def get_merge_strategy(self): | ||
"""Get the merge strategy for how scripted frames should be integrated. | ||
|
||
The merge strategy determines how the scripted frames are combined with the | ||
real unwound frames from the thread's normal unwinder. | ||
|
||
Returns: | ||
int: One of the following lldb.ScriptedFrameProviderMergeStrategy values: | ||
|
||
- lldb.eScriptedFrameProviderMergeStrategyReplace: Replace the entire stack | ||
with scripted frames. The thread will only show frames provided | ||
by this provider. | ||
|
||
- lldb.eScriptedFrameProviderMergeStrategyPrepend: Prepend scripted frames | ||
before the real unwound frames. Useful for adding synthetic frames | ||
at the top of the stack while preserving the actual callstack below. | ||
|
||
- lldb.eScriptedFrameProviderMergeStrategyAppend: Append scripted frames | ||
after the real unwound frames. Useful for showing additional context | ||
after the actual callstack ends. | ||
|
||
- lldb.eScriptedFrameProviderMergeStrategyReplaceByIndex: Replace specific | ||
frames at given indices with scripted frames, keeping other real frames | ||
intact. The idx field in each frame dictionary determines which real | ||
frame to replace (e.g., idx=0 replaces frame 0, idx=2 replaces frame 2). | ||
|
||
The default implementation returns Replace strategy. | ||
|
||
Example: | ||
|
||
.. code-block:: python | ||
|
||
def get_merge_strategy(self): | ||
# Only show our custom frames | ||
return lldb.eScriptedFrameProviderMergeStrategyReplace | ||
|
||
def get_merge_strategy(self): | ||
# Add diagnostic frames on top of real stack | ||
return lldb.eScriptedFrameProviderMergeStrategyPrepend | ||
|
||
def get_merge_strategy(self): | ||
# Replace frame 0 and frame 2 with custom frames, keep others | ||
return lldb.eScriptedFrameProviderMergeStrategyReplaceByIndex | ||
""" | ||
return lldb.eScriptedFrameProviderMergeStrategyReplace | ||
|
||
@abstractmethod | ||
def get_stackframes(self): | ||
"""Get the list of stack frames to provide. | ||
|
||
This method is called when the thread's backtrace is requested | ||
(e.g., via the 'bt' command). The returned frames will be integrated | ||
with the real frames according to the mode returned by get_mode(). | ||
|
||
Returns: | ||
List[Dict]: A list of frame dictionaries, where each dictionary | ||
describes a single stack frame. Each dictionary should contain: | ||
|
||
Required fields: | ||
- idx (int): The frame index (0 for innermost/top frame) | ||
- pc (int): The program counter address for this frame | ||
|
||
Alternatively, you can return a list of ScriptedFrame objects | ||
for more control over frame behavior. | ||
|
||
Example: | ||
|
||
.. code-block:: python | ||
|
||
def get_stackframes(self): | ||
frames = [] | ||
|
||
# Frame 0: Current function | ||
frames.append({ | ||
"idx": 0, | ||
"pc": 0x100001234, | ||
}) | ||
|
||
# Frame 1: Caller | ||
frames.append({ | ||
"idx": 1, | ||
"pc": 0x100001000, | ||
}) | ||
|
||
return frames | ||
|
||
Note: | ||
The frames are indexed from 0 (innermost/newest) to N (outermost/oldest). | ||
""" | ||
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
//===-- 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; | ||
|
||
/// Get the merge strategy for how scripted frames should be integrated with | ||
/// real frames | ||
virtual lldb::ScriptedFrameProviderMergeStrategy GetMergeStrategy() { | ||
return lldb::eScriptedFrameProviderMergeStrategyReplace; | ||
} | ||
|
||
virtual StructuredData::ArraySP | ||
GetStackFrames(lldb::StackFrameListSP real_frames) { | ||
return {}; | ||
} | ||
}; | ||
} // namespace lldb_private | ||
|
||
#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEPROVIDERINTERFACE_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error
seems unused?