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