]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/dap/frames.py
1 # Copyright 2022-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 from gdb
.frames
import frame_iterator
21 from .startup
import in_gdb_thread
24 # A list of all the frames we've reported. A frame's index in the
25 # list is its ID. We don't use a hash here because frames are not
30 # Map from a global thread ID to a memoizing frame iterator.
34 # Clear all the frame IDs.
36 def _clear_frame_ids(evt
):
43 # Clear the frame ID map whenever the inferior runs.
44 gdb
.events
.cont
.connect(_clear_frame_ids
)
49 """Given a frame identifier ID, return the corresponding frame."""
51 return _all_frames
[id]
56 """Given a frame identifier ID, select the corresponding frame."""
57 frame
= frame_for_id(id)
58 frame
.inferior_frame().select()
61 # A simple memoizing iterator. Note that this is not very robust.
62 # For example, you can't start two copies of the iterator and then
63 # alternate fetching items from each. Instead, it implements just
64 # what is needed for the current callers.
65 class _MemoizingIterator
:
66 def __init__(self
, iterator
):
67 self
.iterator
= iterator
71 # First the memoized items.
72 for item
in self
.seen
:
74 # Now memoize new items.
75 for item
in self
.iterator
:
76 self
.seen
.append(item
)
80 # A generator that fetches frames and pairs them with a frame ID. It
81 # yields tuples of the form (ID, ELIDED, FRAME), where ID is the
82 # generated ID, ELIDED is a boolean indicating if the frame should be
83 # elided, and FRAME is the frame itself. This approach lets us
84 # memoize the result and assign consistent IDs, independent of how
85 # "includeAll" is set in the request.
87 def _frame_id_generator():
89 base_iterator
= frame_iterator(gdb
.newest_frame(), 0, -1)
93 # Helper function to assign an ID to a frame.
96 num
= len(_all_frames
)
97 _all_frames
.append(frame
)
100 def yield_frames(iterator
, for_elided
):
101 for frame
in iterator
:
102 # Unfortunately the frame filter docs don't describe
103 # whether the elided frames conceptually come before or
104 # after the eliding frame. Here we choose after.
105 yield (get_id(frame
), for_elided
, frame
)
107 elided
= frame
.elided()
108 if elided
is not None:
109 yield from yield_frames(frame
.elided(), True)
111 yield from yield_frames(base_iterator
, False)
114 # Return the memoizing frame iterator for the selected thread.
116 def _get_frame_iterator():
117 thread_id
= gdb
.selected_thread().global_num
119 if thread_id
not in _iter_map
:
120 _iter_map
[thread_id
] = _MemoizingIterator(_frame_id_generator())
121 return _iter_map
[thread_id
]
124 # A helper function that creates an iterable that returns (ID, FRAME)
125 # pairs. It uses the memoizing frame iterator, but also handles the
126 # "includeAll" member of StackFrameFormat.
128 def dap_frame_generator(frame_low
, levels
, include_all
):
129 """A generator that yields identifiers and frames.
131 Each element is a pair of the form (ID, FRAME).
132 ID is the internally-assigned frame ID.
133 FRAME is a FrameDecorator of some kind.
135 Arguments are as to the stackTrace request."""
137 base_iterator
= _get_frame_iterator()
140 base_iterator
= itertools
.filterfalse(lambda item
: item
[1], base_iterator
)
143 # Zero means all remaining frames.
146 frame_high
= frame_low
+ levels
147 base_iterator
= itertools
.islice(base_iterator
, frame_low
, frame_high
)
149 for ident
, _
, frame
in base_iterator
: