Skip to content

Commit 3d734e9

Browse files
committed
[lldb] Introduce SBFrameList for lazy frame iteration
This patch introduces `SBFrameList`, a new SBAPI class that allows iterating over stack frames lazily without calling `SBThread::GetFrameAtIndex` in a loop. The new `SBThread::GetFrames()` method returns an `SBFrameList` that supports Python iteration (`for frame in frame_list:`), indexing (`frame_list[0]`, `frame_list[-1]`), and length queries (`len()`). The implementation uses `StackFrameListSP` as the opaque pointer, sharing the thread's underlying frame list to ensure frames are materialized on-demand. This is particularly useful for ScriptedFrameProviders, where user scripts can now iterate, filter, and replace frames lazily without materializing the entire stack upfront. Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 6d44b90 commit 3d734e9

File tree

17 files changed

+457
-1
lines changed

17 files changed

+457
-1
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
%feature("docstring",
2+
"Represents a list of :py:class:`SBFrame` objects."
3+
) lldb::SBFrameList;
4+
5+
%feature("autodoc", "GetSize(SBFrameList self) -> uint32_t") lldb::SBFrameList::GetSize;
6+
%feature("docstring", "
7+
Returns the number of frames in the list."
8+
) lldb::SBFrameList::GetSize;
9+
10+
%feature("autodoc", "GetFrameAtIndex(SBFrameList self, uint32_t idx) -> SBFrame") lldb::SBFrameList::GetFrameAtIndex;
11+
%feature("docstring", "
12+
Returns the frame at the given index."
13+
) lldb::SBFrameList::GetFrameAtIndex;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
%extend lldb::SBFrameList {
2+
3+
#ifdef SWIGPYTHON
4+
%nothreadallow;
5+
#endif
6+
std::string lldb::SBFrameList::__str__ (){
7+
lldb::SBStream description;
8+
const size_t n = $self->GetSize();
9+
if (n)
10+
{
11+
for (size_t i=0; i<n; ++i)
12+
$self->GetFrameAtIndex(i).GetDescription(description);
13+
}
14+
else
15+
{
16+
description.Printf("<empty> lldb.SBFrameList()");
17+
}
18+
const char *desc = description.GetData();
19+
size_t desc_len = description.GetSize();
20+
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
21+
--desc_len;
22+
return std::string(desc, desc_len);
23+
}
24+
#ifdef SWIGPYTHON
25+
%clearnothreadallow;
26+
#endif
27+
28+
#ifdef SWIGPYTHON
29+
%pythoncode %{
30+
def __iter__(self):
31+
'''Iterate over all frames in a lldb.SBFrameList object.'''
32+
return lldb_iter(self, 'GetSize', 'GetFrameAtIndex')
33+
34+
def __len__(self):
35+
return int(self.GetSize())
36+
37+
def __getitem__(self, key):
38+
count = len(self)
39+
if type(key) is int:
40+
if -count <= key < count:
41+
key %= count
42+
return self.GetFrameAtIndex(key)
43+
return None
44+
%}
45+
#endif
46+
}

lldb/bindings/interface/SBThreadExtensions.i

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ STRING_EXTENSION_OUTSIDE(SBThread)
4141
def get_thread_frames(self):
4242
'''An accessor function that returns a list() that contains all frames in a lldb.SBThread object.'''
4343
frames = []
44-
for frame in self:
44+
frame_list = self.GetFrames()
45+
for frame in frame_list:
4546
frames.append(frame)
4647
return frames
4748

lldb/bindings/interfaces.swig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
%include "./interface/SBFileSpecListDocstrings.i"
4040
%include "./interface/SBFormatDocstrings.i"
4141
%include "./interface/SBFrameDocstrings.i"
42+
%include "./interface/SBFrameListDocstrings.i"
4243
%include "./interface/SBFunctionDocstrings.i"
4344
%include "./interface/SBHostOSDocstrings.i"
4445
%include "./interface/SBInstructionDocstrings.i"
@@ -118,6 +119,7 @@
118119
%include "lldb/API/SBFileSpecList.h"
119120
%include "lldb/API/SBFormat.h"
120121
%include "lldb/API/SBFrame.h"
122+
%include "lldb/API/SBFrameList.h"
121123
%include "lldb/API/SBFunction.h"
122124
%include "lldb/API/SBHostOS.h"
123125
%include "lldb/API/SBInstruction.h"
@@ -192,6 +194,7 @@
192194
%include "./interface/SBFileSpecExtensions.i"
193195
%include "./interface/SBFileSpecListExtensions.i"
194196
%include "./interface/SBFrameExtensions.i"
197+
%include "./interface/SBFrameListExtensions.i"
195198
%include "./interface/SBFunctionExtensions.i"
196199
%include "./interface/SBInstructionExtensions.i"
197200
%include "./interface/SBInstructionListExtensions.i"

lldb/include/lldb/API/LLDB.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "lldb/API/SBFileSpecList.h"
3838
#include "lldb/API/SBFormat.h"
3939
#include "lldb/API/SBFrame.h"
40+
#include "lldb/API/SBFrameList.h"
4041
#include "lldb/API/SBFunction.h"
4142
#include "lldb/API/SBHostOS.h"
4243
#include "lldb/API/SBInstruction.h"

lldb/include/lldb/API/SBDefines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class LLDB_API SBFileSpec;
7676
class LLDB_API SBFileSpecList;
7777
class LLDB_API SBFormat;
7878
class LLDB_API SBFrame;
79+
class LLDB_API SBFrameList;
7980
class LLDB_API SBFunction;
8081
class LLDB_API SBHostOS;
8182
class LLDB_API SBInstruction;

lldb/include/lldb/API/SBFrame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class LLDB_API SBFrame {
222222
protected:
223223
friend class SBBlock;
224224
friend class SBExecutionContext;
225+
friend class SBFrameList;
225226
friend class SBInstruction;
226227
friend class SBThread;
227228
friend class SBValue;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===-- SBFrameList.h -------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_API_SBFRAMELIST_H
10+
#define LLDB_API_SBFRAMELIST_H
11+
12+
#include "lldb/API/SBDefines.h"
13+
14+
namespace lldb {
15+
16+
class LLDB_API SBFrameList {
17+
public:
18+
SBFrameList();
19+
20+
SBFrameList(const lldb::SBFrameList &rhs);
21+
22+
~SBFrameList();
23+
24+
const lldb::SBFrameList &operator=(const lldb::SBFrameList &rhs);
25+
26+
explicit operator bool() const;
27+
28+
bool IsValid() const;
29+
30+
uint32_t GetSize() const;
31+
32+
lldb::SBFrame GetFrameAtIndex(uint32_t idx) const;
33+
34+
void Clear();
35+
36+
void Append(const lldb::SBFrame &frame);
37+
38+
void Append(const lldb::SBFrameList &frame_list);
39+
40+
bool GetDescription(lldb::SBStream &description) const;
41+
42+
protected:
43+
friend class SBThread;
44+
45+
private:
46+
SBFrameList(const lldb::StackFrameListSP &frame_list_sp);
47+
48+
void SetOpaque(const lldb::StackFrameListSP &frame_list_sp);
49+
50+
lldb::StackFrameListSP m_opaque_sp;
51+
};
52+
53+
} // namespace lldb
54+
55+
#endif // LLDB_API_SBFRAMELIST_H

lldb/include/lldb/API/SBStream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class LLDB_API SBStream {
8181
friend class SBFileSpec;
8282
friend class SBFileSpecList;
8383
friend class SBFrame;
84+
friend class SBFrameList;
8485
friend class SBFunction;
8586
friend class SBInstruction;
8687
friend class SBInstructionList;

lldb/include/lldb/API/SBThread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class LLDB_API SBThread {
178178

179179
lldb::SBFrame GetFrameAtIndex(uint32_t idx);
180180

181+
lldb::SBFrameList GetFrames();
182+
181183
lldb::SBFrame GetSelectedFrame();
182184

183185
lldb::SBFrame SetSelectedFrame(uint32_t frame_idx);

0 commit comments

Comments
 (0)