Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / python / lib / gdb / frames.py
CommitLineData
1e611234 1# Frame-filter commands.
88b9d363 2# Copyright (C) 2013-2022 Free Software Foundation, Inc.
1e611234
PM
3
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""Internal functions for working with frame-filters."""
18
19import gdb
20from gdb.FrameIterator import FrameIterator
21from gdb.FrameDecorator import FrameDecorator
22import itertools
23import collections
24
13123da8 25
1e611234 26def get_priority(filter_item):
13123da8 27 """Internal worker function to return the frame-filter's priority
1e611234
PM
28 from a frame filter object. This is a fail free function as it is
29 used in sorting and filtering. If a badly implemented frame
30 filter does not implement the priority attribute, return zero
31 (otherwise sorting/filtering will fail and prevent other frame
32 filters from executing).
33
34 Arguments:
35 filter_item: An object conforming to the frame filter
36 interface.
37
38 Returns:
39 The priority of the frame filter from the "priority"
40 attribute, or zero.
41 """
42 # Do not fail here, as the sort will fail. If a filter has not
43 # (incorrectly) set a priority, set it to zero.
44 return getattr(filter_item, "priority", 0)
45
13123da8 46
1e611234 47def set_priority(filter_item, priority):
13123da8 48 """Internal worker function to set the frame-filter's priority.
1e611234
PM
49
50 Arguments:
51 filter_item: An object conforming to the frame filter
52 interface.
53 priority: The priority to assign as an integer.
54 """
55
56 filter_item.priority = priority
57
13123da8 58
1e611234 59def get_enabled(filter_item):
13123da8 60 """Internal worker function to return a filter's enabled state
1e611234
PM
61 from a frame filter object. This is a fail free function as it is
62 used in sorting and filtering. If a badly implemented frame
63 filter does not implement the enabled attribute, return False
64 (otherwise sorting/filtering will fail and prevent other frame
65 filters from executing).
66
67 Arguments:
68 filter_item: An object conforming to the frame filter
69 interface.
70
71 Returns:
72 The enabled state of the frame filter from the "enabled"
73 attribute, or False.
74 """
75
76 # If the filter class is badly implemented when called from the
77 # Python filter command, do not cease filter operations, just set
78 # enabled to False.
79 return getattr(filter_item, "enabled", False)
80
13123da8 81
1e611234 82def set_enabled(filter_item, state):
13123da8 83 """Internal Worker function to set the frame-filter's enabled
1e611234
PM
84 state.
85
86 Arguments:
87 filter_item: An object conforming to the frame filter
88 interface.
89 state: True or False, depending on desired state.
90 """
91
92 filter_item.enabled = state
93
13123da8 94
1e611234 95def return_list(name):
13123da8 96 """Internal Worker function to return the frame filter
1e611234
PM
97 dictionary, depending on the name supplied as an argument. If the
98 name is not "all", "global" or "progspace", it is assumed to name
99 an object-file.
100
101 Arguments:
102 name: The name of the list, as specified by GDB user commands.
103
104 Returns:
105 A dictionary object for a single specified dictionary, or a
106 list containing all the items for "all"
107
108 Raises:
109 gdb.GdbError: A dictionary of that name cannot be found.
110 """
111
112 # If all dictionaries are wanted in the case of "all" we
113 # cannot return a combined dictionary as keys() may clash in
114 # between different dictionaries. As we just want all the frame
115 # filters to enable/disable them all, just return the combined
8f28f522 116 # items() as a chained iterator of dictionary values.
1e611234 117 if name == "all":
8f28f522
PM
118 glob = gdb.frame_filters.values()
119 prog = gdb.current_progspace().frame_filters.values()
120 return_iter = itertools.chain(glob, prog)
1e611234 121 for objfile in gdb.objfiles():
8f28f522
PM
122 return_iter = itertools.chain(return_iter, objfile.frame_filters.values())
123
124 return return_iter
1e611234
PM
125
126 if name == "global":
127 return gdb.frame_filters
128 else:
129 if name == "progspace":
130 cp = gdb.current_progspace()
131 return cp.frame_filters
132 else:
133 for objfile in gdb.objfiles():
134 if name == objfile.filename:
135 return objfile.frame_filters
136
137 msg = "Cannot find frame-filter dictionary for '" + name + "'"
138 raise gdb.GdbError(msg)
139
13123da8 140
1e611234 141def _sort_list():
13123da8 142 """Internal Worker function to merge all known frame-filter
1e611234
PM
143 lists, prune any filters with the state set to "disabled", and
144 sort the list on the frame-filter's "priority" attribute.
145
146 Returns:
147 sorted_list: A sorted, pruned list of frame filters to
148 execute.
149 """
150
8f28f522 151 all_filters = return_list("all")
13123da8 152 sorted_frame_filters = sorted(all_filters, key=get_priority, reverse=True)
1e611234 153
13123da8 154 sorted_frame_filters = filter(get_enabled, sorted_frame_filters)
1e611234
PM
155
156 return sorted_frame_filters
157
13123da8 158
1e611234 159def execute_frame_filters(frame, frame_low, frame_high):
13123da8 160 """Internal function called from GDB that will execute the chain
1e611234
PM
161 of frame filters. Each filter is executed in priority order.
162 After the execution completes, slice the iterator to frame_low -
163 frame_high range.
164
165 Arguments:
166 frame: The initial frame.
167
168 frame_low: The low range of the slice. If this is a negative
169 integer then it indicates a backward slice (ie bt -4) which
170 counts backward from the last frame in the backtrace.
171
172 frame_high: The high range of the slice. If this is -1 then
173 it indicates all frames until the end of the stack from
174 frame_low.
175
176 Returns:
177 frame_iterator: The sliced iterator after all frame
178 filters have had a change to execute, or None if no frame
179 filters are registered.
180 """
181
182 # Get a sorted list of frame filters.
8f28f522 183 sorted_list = list(_sort_list())
1e611234
PM
184
185 # Check to see if there are any frame-filters. If not, just
186 # return None and let default backtrace printing occur.
187 if len(sorted_list) == 0:
188 return None
189
190 frame_iterator = FrameIterator(frame)
191
8f28f522
PM
192 # Apply a basic frame decorator to all gdb.Frames. This unifies
193 # the interface. Python 3.x moved the itertools.imap
194 # functionality to map(), so check if it is available.
13123da8 195 if hasattr(itertools, "imap"):
8f28f522
PM
196 frame_iterator = itertools.imap(FrameDecorator, frame_iterator)
197 else:
198 frame_iterator = map(FrameDecorator, frame_iterator)
1e611234
PM
199
200 for ff in sorted_list:
201 frame_iterator = ff.filter(frame_iterator)
202
203 # Slicing
204
205 # Is this a slice from the end of the backtrace, ie bt -2?
206 if frame_low < 0:
207 count = 0
208 slice_length = abs(frame_low)
209 # We cannot use MAXLEN argument for deque as it is 2.6 onwards
210 # and some GDB versions might be < 2.6.
211 sliced = collections.deque()
212
213 for frame_item in frame_iterator:
214 if count >= slice_length:
13123da8 215 sliced.popleft()
1e611234
PM
216 count = count + 1
217 sliced.append(frame_item)
218
219 return iter(sliced)
220
221 # -1 for frame_high means until the end of the backtrace. Set to
222 # None if that is the case, to indicate to itertools.islice to
223 # slice to the end of the iterator.
224 if frame_high == -1:
225 frame_high = None
226 else:
227 # As frames start from 0, add one to frame_high so islice
228 # correctly finds the end
13123da8 229 frame_high = frame_high + 1
1e611234
PM
230
231 sliced = itertools.islice(frame_iterator, frame_low, frame_high)
232
233 return sliced
This page took 1.067982 seconds and 4 git commands to generate.