]> Git Repo - binutils.git/blob - gdb/python/lib/gdb/command/frame_filters.py
5ea562e751157c283ba1dafdb79b3c7e3f2bcec8
[binutils.git] / gdb / python / lib / gdb / command / frame_filters.py
1 # Frame-filter commands.
2 # Copyright (C) 2013-2021 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()
This page took 0.043136 seconds and 2 git commands to generate.