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