[Lldb-commits] [lldb] [lldb] Introduce ScriptedFrameProvider for real threads (PR #161870)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 30 14:32:30 PDT 2025
================
@@ -0,0 +1,119 @@
+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 = 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
+
+ @abstractmethod
+ def get_frame_at_index(self, real_frames, index):
+ """Get a single stack frame at the given index.
+
+ This method is called lazily when a specific frame is needed in the
+ thread's backtrace (e.g., via the 'bt' command). Each frame is
+ requested individually as needed.
+
+ Args:
+ real_frames (lldb.SBFrameList): The actual unwound frames from the
+ thread's normal unwinder. This allows you to access real frames
+ by index. The frames are materialized lazily as you access them.
+ index (int): The frame index to retrieve (0 for innermost/top frame).
+
+ Returns:
+ Dict or None: A frame dictionary describing the stack frame, or None
+ if no frame exists at this index. The 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 ScriptedFrame object for full control over frame behavior
+ - An integer representing a real frame index to reuse
----------------
jimingham wrote:
You should give an example of this one, since in the example below you seem to be returning a real frame but not by returning an index. What do you intend by this?
https://github.com/llvm/llvm-project/pull/161870
More information about the lldb-commits
mailing list