]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/command/frame_filters.py
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / command / frame_filters.py
1 # Frame-filter commands.
2 # Copyright (C) 2013-2024 Free Software Foundation, Inc.
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 """GDB commands for working with frame-filters."""
18
19 import sys
20 import gdb
21 import gdb.frames
22
23
24 # GDB Commands.
25 class SetFilterPrefixCmd(gdb.Command):
26 """Prefix command for 'set' frame-filter related operations."""
27
28 def __init__(self):
29 super(SetFilterPrefixCmd, self).__init__(
30 "set frame-filter", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True
31 )
32
33
34 class ShowFilterPrefixCmd(gdb.Command):
35 """Prefix command for 'show' frame-filter related operations."""
36
37 def __init__(self):
38 super(ShowFilterPrefixCmd, self).__init__(
39 "show frame-filter", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True
40 )
41
42
43 class InfoFrameFilter(gdb.Command):
44 """List all registered Python frame-filters.
45
46 Usage: info frame-filters"""
47
48 def __init__(self):
49 super(InfoFrameFilter, self).__init__("info frame-filter", gdb.COMMAND_DATA)
50
51 @staticmethod
52 def enabled_string(state):
53 """Return "Yes" if filter is enabled, otherwise "No"."""
54 if state:
55 return "Yes"
56 else:
57 return "No"
58
59 def print_list(self, title, frame_filters, blank_line):
60 sorted_frame_filters = sorted(
61 frame_filters.items(),
62 key=lambda i: gdb.frames.get_priority(i[1]),
63 reverse=True,
64 )
65
66 if len(sorted_frame_filters) == 0:
67 return 0
68
69 print(title)
70 print(" Priority Enabled Name")
71 for frame_filter in sorted_frame_filters:
72 name = frame_filter[0]
73 try:
74 priority = "{:<8}".format(str(gdb.frames.get_priority(frame_filter[1])))
75 enabled = "{:<7}".format(
76 self.enabled_string(gdb.frames.get_enabled(frame_filter[1]))
77 )
78 print(" %s %s %s" % (priority, enabled, name))
79 except Exception:
80 e = sys.exc_info()[1]
81 print(" Error printing filter '" + name + "': " + str(e))
82 if blank_line:
83 print("")
84 return 1
85
86 def invoke(self, arg, from_tty):
87 any_printed = self.print_list("global frame-filters:", gdb.frame_filters, True)
88
89 cp = gdb.current_progspace()
90 any_printed += self.print_list(
91 "progspace %s frame-filters:" % cp.filename, cp.frame_filters, True
92 )
93
94 for objfile in gdb.objfiles():
95 any_printed += self.print_list(
96 "objfile %s frame-filters:" % objfile.filename,
97 objfile.frame_filters,
98 False,
99 )
100
101 if any_printed == 0:
102 print("No frame filters.")
103
104
105 # Internal enable/disable functions.
106
107
108 def _enable_parse_arg(cmd_name, arg):
109 """Internal worker function to take an argument from
110 enable/disable and return a tuple of arguments.
111
112 Arguments:
113 cmd_name: Name of the command invoking this function.
114 args: The argument as a string.
115
116 Returns:
117 A tuple containing the dictionary, and the argument, or just
118 the dictionary in the case of "all".
119 """
120
121 argv = gdb.string_to_argv(arg)
122 argc = len(argv)
123 if argc == 0:
124 raise gdb.GdbError(cmd_name + " requires an argument")
125 if argv[0] == "all":
126 if argc > 1:
127 raise gdb.GdbError(
128 cmd_name + ": with 'all' " "you may not specify a filter."
129 )
130 elif argc != 2:
131 raise gdb.GdbError(cmd_name + " takes exactly two arguments.")
132
133 return argv
134
135
136 def _do_enable_frame_filter(command_tuple, flag):
137 """Worker for enabling/disabling frame_filters.
138
139 Arguments:
140 command_type: A tuple with the first element being the
141 frame filter dictionary, and the second being
142 the frame filter name.
143 flag: True for Enable, False for Disable.
144 """
145
146 list_op = command_tuple[0]
147 op_list = gdb.frames.return_list(list_op)
148
149 if list_op == "all":
150 for item in op_list:
151 gdb.frames.set_enabled(item, flag)
152 else:
153 frame_filter = command_tuple[1]
154 try:
155 ff = op_list[frame_filter]
156 except KeyError:
157 msg = "frame-filter '" + str(frame_filter) + "' not found."
158 raise gdb.GdbError(msg)
159
160 gdb.frames.set_enabled(ff, flag)
161
162
163 def _complete_frame_filter_list(text, word, all_flag):
164 """Worker for frame filter dictionary name completion.
165
166 Arguments:
167 text: The full text of the command line.
168 word: The most recent word of the command line.
169 all_flag: Whether to include the word "all" in completion.
170
171 Returns:
172 A list of suggested frame filter dictionary name completions
173 from text/word analysis. This list can be empty when there
174 are no suggestions for completion.
175 """
176 if all_flag:
177 filter_locations = ["all", "global", "progspace"]
178 else:
179 filter_locations = ["global", "progspace"]
180 for objfile in gdb.objfiles():
181 filter_locations.append(objfile.filename)
182
183 # If the user just asked for completions with no completion
184 # hints, just return all the frame filter dictionaries we know
185 # about.
186 if text == "":
187 return filter_locations
188
189 # Otherwise filter on what we know.
190 flist = filter(lambda x, y=text: x.startswith(y), filter_locations)
191
192 # If we only have one completion, complete it and return it.
193 if len(flist) == 1:
194 flist[0] = flist[0][len(text) - len(word) :]
195
196 # Otherwise, return an empty list, or a list of frame filter
197 # dictionaries that the previous filter operation returned.
198 return flist
199
200
201 def _complete_frame_filter_name(word, printer_dict):
202 """Worker for frame filter name completion.
203
204 Arguments:
205
206 word: The most recent word of the command line.
207
208 printer_dict: The frame filter dictionary to search for frame
209 filter name completions.
210
211 Returns: A list of suggested frame filter name completions
212 from word analysis of the frame filter dictionary. This list
213 can be empty when there are no suggestions for completion.
214 """
215
216 printer_keys = printer_dict.keys()
217 if word == "":
218 return printer_keys
219
220 flist = filter(lambda x, y=word: x.startswith(y), printer_keys)
221 return flist
222
223
224 class EnableFrameFilter(gdb.Command):
225 """GDB command to enable the specified frame-filter.
226
227 Usage: enable frame-filter DICTIONARY [NAME]
228
229 DICTIONARY is the name of the frame filter dictionary on which to
230 operate. If dictionary is set to "all", perform operations on all
231 dictionaries. Named dictionaries are: "global" for the global
232 frame filter dictionary, "progspace" for the program space's frame
233 filter dictionary. If either all, or the two named dictionaries
234 are not specified, the dictionary name is assumed to be the name
235 of an "objfile" -- a shared library or an executable.
236
237 NAME matches the name of the frame-filter to operate on."""
238
239 def __init__(self):
240 super(EnableFrameFilter, self).__init__("enable frame-filter", gdb.COMMAND_DATA)
241
242 def complete(self, text, word):
243 """Completion function for both frame filter dictionary, and
244 frame filter name."""
245 if text.count(" ") == 0:
246 return _complete_frame_filter_list(text, word, True)
247 else:
248 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
249 return _complete_frame_filter_name(word, printer_list)
250
251 def invoke(self, arg, from_tty):
252 command_tuple = _enable_parse_arg("enable frame-filter", arg)
253 _do_enable_frame_filter(command_tuple, True)
254
255
256 class DisableFrameFilter(gdb.Command):
257 """GDB command to disable the specified frame-filter.
258
259 Usage: disable frame-filter DICTIONARY [NAME]
260
261 DICTIONARY is the name of the frame filter dictionary on which to
262 operate. If dictionary is set to "all", perform operations on all
263 dictionaries. Named dictionaries are: "global" for the global
264 frame filter dictionary, "progspace" for the program space's frame
265 filter dictionary. If either all, or the two named dictionaries
266 are not specified, the dictionary name is assumed to be the name
267 of an "objfile" -- a shared library or an executable.
268
269 NAME matches the name of the frame-filter to operate on."""
270
271 def __init__(self):
272 super(DisableFrameFilter, self).__init__(
273 "disable frame-filter", gdb.COMMAND_DATA
274 )
275
276 def complete(self, text, word):
277 """Completion function for both frame filter dictionary, and
278 frame filter name."""
279 if text.count(" ") == 0:
280 return _complete_frame_filter_list(text, word, True)
281 else:
282 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
283 return _complete_frame_filter_name(word, printer_list)
284
285 def invoke(self, arg, from_tty):
286 command_tuple = _enable_parse_arg("disable frame-filter", arg)
287 _do_enable_frame_filter(command_tuple, False)
288
289
290 class SetFrameFilterPriority(gdb.Command):
291 """GDB command to set the priority of the specified frame-filter.
292
293 Usage: set frame-filter priority DICTIONARY NAME PRIORITY
294
295 DICTIONARY is the name of the frame filter dictionary on which to
296 operate. Named dictionaries are: "global" for the global frame
297 filter dictionary, "progspace" for the program space's framefilter
298 dictionary. If either of these two are not specified, the
299 dictionary name is assumed to be the name of an "objfile" -- a
300 shared library or an executable.
301
302 NAME matches the name of the frame filter to operate on.
303
304 PRIORITY is the an integer to assign the new priority to the frame
305 filter."""
306
307 def __init__(self):
308 super(SetFrameFilterPriority, self).__init__(
309 "set frame-filter " "priority", gdb.COMMAND_DATA
310 )
311
312 def _parse_pri_arg(self, arg):
313 """Internal worker to parse a priority from a tuple.
314
315 Arguments:
316 arg: Tuple which contains the arguments from the command.
317
318 Returns:
319 A tuple containing the dictionary, name and priority from
320 the arguments.
321
322 Raises:
323 gdb.GdbError: An error parsing the arguments.
324 """
325
326 argv = gdb.string_to_argv(arg)
327 argc = len(argv)
328 if argc != 3:
329 print("set frame-filter priority " "takes exactly three arguments.")
330 return None
331
332 return argv
333
334 def _set_filter_priority(self, command_tuple):
335 """Internal worker for setting priority of frame-filters, by
336 parsing a tuple and calling _set_priority with the parsed
337 tuple.
338
339 Arguments:
340 command_tuple: Tuple which contains the arguments from the
341 command.
342 """
343
344 list_op = command_tuple[0]
345 frame_filter = command_tuple[1]
346
347 # GDB returns arguments as a string, so convert priority to
348 # a number.
349 priority = int(command_tuple[2])
350
351 op_list = gdb.frames.return_list(list_op)
352
353 try:
354 ff = op_list[frame_filter]
355 except KeyError:
356 msg = "frame-filter '" + str(frame_filter) + "' not found."
357 raise gdb.GdbError(msg)
358
359 gdb.frames.set_priority(ff, priority)
360
361 def complete(self, text, word):
362 """Completion function for both frame filter dictionary, and
363 frame filter name."""
364 if text.count(" ") == 0:
365 return _complete_frame_filter_list(text, word, False)
366 else:
367 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
368 return _complete_frame_filter_name(word, printer_list)
369
370 def invoke(self, arg, from_tty):
371 command_tuple = self._parse_pri_arg(arg)
372 if command_tuple is not None:
373 self._set_filter_priority(command_tuple)
374
375
376 class ShowFrameFilterPriority(gdb.Command):
377 """GDB command to show the priority of the specified frame-filter.
378
379 Usage: show frame-filter priority DICTIONARY NAME
380
381 DICTIONARY is the name of the frame filter dictionary on which to
382 operate. Named dictionaries are: "global" for the global frame
383 filter dictionary, "progspace" for the program space's framefilter
384 dictionary. If either of these two are not specified, the
385 dictionary name is assumed to be the name of an "objfile" -- a
386 shared library or an executable.
387
388 NAME matches the name of the frame-filter to operate on."""
389
390 def __init__(self):
391 super(ShowFrameFilterPriority, self).__init__(
392 "show frame-filter " "priority", gdb.COMMAND_DATA
393 )
394
395 def _parse_pri_arg(self, arg):
396 """Internal worker to parse a dictionary and name from a
397 tuple.
398
399 Arguments:
400 arg: Tuple which contains the arguments from the command.
401
402 Returns:
403 A tuple containing the dictionary, and frame filter name.
404
405 Raises:
406 gdb.GdbError: An error parsing the arguments.
407 """
408
409 argv = gdb.string_to_argv(arg)
410 argc = len(argv)
411 if argc != 2:
412 print("show frame-filter priority " "takes exactly two arguments.")
413 return None
414
415 return argv
416
417 def get_filter_priority(self, frame_filters, name):
418 """Worker for retrieving the priority of frame_filters.
419
420 Arguments:
421 frame_filters: Name of frame filter dictionary.
422 name: object to select printers.
423
424 Returns:
425 The priority of the frame filter.
426
427 Raises:
428 gdb.GdbError: A frame filter cannot be found.
429 """
430
431 op_list = gdb.frames.return_list(frame_filters)
432
433 try:
434 ff = op_list[name]
435 except KeyError:
436 msg = "frame-filter '" + str(name) + "' not found."
437 raise gdb.GdbError(msg)
438
439 return gdb.frames.get_priority(ff)
440
441 def complete(self, text, word):
442 """Completion function for both frame filter dictionary, and
443 frame filter name."""
444
445 if text.count(" ") == 0:
446 return _complete_frame_filter_list(text, word, False)
447 else:
448 printer_list = frame._return_list(text.split()[0].rstrip())
449 return _complete_frame_filter_name(word, printer_list)
450
451 def invoke(self, arg, from_tty):
452 command_tuple = self._parse_pri_arg(arg)
453 if command_tuple is None:
454 return
455 filter_name = command_tuple[1]
456 list_name = command_tuple[0]
457 try:
458 priority = self.get_filter_priority(list_name, filter_name)
459 except Exception:
460 e = sys.exc_info()[1]
461 print("Error printing filter priority for '" + name + "':" + str(e))
462 else:
463 print(
464 "Priority of filter '"
465 + filter_name
466 + "' in list '"
467 + list_name
468 + "' is: "
469 + str(priority)
470 )
471
472
473 # Register commands
474 SetFilterPrefixCmd()
475 ShowFilterPrefixCmd()
476 InfoFrameFilter()
477 EnableFrameFilter()
478 DisableFrameFilter()
479 SetFrameFilterPriority()
480 ShowFrameFilterPriority()