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