1 # Frame-filter commands.
2 # Copyright (C) 2013-2018 Free Software Foundation, Inc.
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.
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.
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/>.
17 """GDB commands for working with frame-filters."""
22 from gdb.FrameIterator import FrameIterator
23 from gdb.FrameDecorator import FrameDecorator
28 class SetFilterPrefixCmd(gdb.Command):
29 """Prefix command for 'set' frame-filter related operations."""
32 super(SetFilterPrefixCmd, self).__init__("set frame-filter",
34 gdb.COMPLETE_NONE, True)
36 class ShowFilterPrefixCmd(gdb.Command):
37 """Prefix command for 'show' frame-filter related operations."""
39 super(ShowFilterPrefixCmd, self).__init__("show frame-filter",
41 gdb.COMPLETE_NONE, True)
42 class InfoFrameFilter(gdb.Command):
43 """List all registered Python frame-filters.
45 Usage: info frame-filters
49 super(InfoFrameFilter, self).__init__("info frame-filter",
52 def enabled_string(state):
53 """Return "Yes" if filter is enabled, otherwise "No"."""
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]),
64 if len(sorted_frame_filters) == 0:
68 print(" Priority Enabled Name")
69 for frame_filter in sorted_frame_filters:
70 name = frame_filter[0]
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))
79 print(" Error printing filter '"+name+"': "+str(e))
84 def invoke(self, arg, from_tty):
85 any_printed = self.print_list("global frame-filters:", gdb.frame_filters, True)
87 cp = gdb.current_progspace()
88 any_printed += self.print_list("progspace %s frame-filters:" % cp.filename,
89 cp.frame_filters, True)
91 for objfile in gdb.objfiles():
92 any_printed += self.print_list("objfile %s frame-filters:" % objfile.filename,
93 objfile.frame_filters, False)
96 print ("No frame filters.")
98 # Internal enable/disable functions.
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.
105 cmd_name: Name of the command invoking this function.
106 args: The argument as a string.
109 A tuple containing the dictionary, and the argument, or just
110 the dictionary in the case of "all".
113 argv = gdb.string_to_argv(arg);
115 if argv[0] == "all" and argc > 1:
116 raise gdb.GdbError(cmd_name + ": with 'all' " \
117 "you may not specify a filter.")
119 if argv[0] != "all" and argc != 2:
120 raise gdb.GdbError(cmd_name + " takes exactly two arguments.")
124 def _do_enable_frame_filter(command_tuple, flag):
125 """Worker for enabling/disabling frame_filters.
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.
134 list_op = command_tuple[0]
135 op_list = gdb.frames.return_list(list_op)
139 gdb.frames.set_enabled(item, flag)
141 frame_filter = command_tuple[1]
143 ff = op_list[frame_filter]
145 msg = "frame-filter '" + str(frame_filter) + "' not found."
146 raise gdb.GdbError(msg)
148 gdb.frames.set_enabled(ff, flag)
150 def _complete_frame_filter_list(text, word, all_flag):
151 """Worker for frame filter dictionary name completion.
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.
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.
164 filter_locations = ["all", "global", "progspace"]
166 filter_locations = ["global", "progspace"]
167 for objfile in gdb.objfiles():
168 filter_locations.append(objfile.filename)
170 # If the user just asked for completions with no completion
171 # hints, just return all the frame filter dictionaries we know
174 return filter_locations
176 # Otherwise filter on what we know.
177 flist = filter(lambda x,y=text:x.startswith(y), filter_locations)
179 # If we only have one completion, complete it and return it.
181 flist[0] = flist[0][len(text)-len(word):]
183 # Otherwise, return an empty list, or a list of frame filter
184 # dictionaries that the previous filter operation returned.
187 def _complete_frame_filter_name(word, printer_dict):
188 """Worker for frame filter name completion.
192 word: The most recent word of the command line.
194 printer_dict: The frame filter dictionary to search for frame
195 filter name completions.
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.
202 printer_keys = printer_dict.keys()
206 flist = filter(lambda x,y=word:x.startswith(y), printer_keys)
209 class EnableFrameFilter(gdb.Command):
210 """GDB command to disable the specified frame-filter.
212 Usage: enable frame-filter enable DICTIONARY [NAME]
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.
222 NAME matches the name of the frame-filter to operate on. If
223 DICTIONARY is "all", NAME is ignored.
226 super(EnableFrameFilter, self).__init__("enable frame-filter",
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)
234 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
235 return _complete_frame_filter_name(word, printer_list)
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)
242 class DisableFrameFilter(gdb.Command):
243 """GDB command to disable the specified frame-filter.
245 Usage: disable frame-filter disable DICTIONARY [NAME]
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.
255 NAME matches the name of the frame-filter to operate on. If
256 DICTIONARY is "all", NAME is ignored.
259 super(DisableFrameFilter, self).__init__("disable frame-filter",
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)
268 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
269 return _complete_frame_filter_name(word, printer_list)
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)
275 class SetFrameFilterPriority(gdb.Command):
276 """GDB command to set the priority of the specified frame-filter.
278 Usage: set frame-filter priority DICTIONARY NAME PRIORITY
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.
286 NAME matches the name of the frame filter to operate on.
288 PRIORITY is the an integer to assign the new priority to the frame
293 super(SetFrameFilterPriority, self).__init__("set frame-filter " \
297 def _parse_pri_arg(self, arg):
298 """Internal worker to parse a priority from a tuple.
301 arg: Tuple which contains the arguments from the command.
304 A tuple containing the dictionary, name and priority from
308 gdb.GdbError: An error parsing the arguments.
311 argv = gdb.string_to_argv(arg);
314 print("set frame-filter priority " \
315 "takes exactly three arguments.")
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
326 command_tuple: Tuple which contains the arguments from the
330 list_op = command_tuple[0]
331 frame_filter = command_tuple[1]
333 # GDB returns arguments as a string, so convert priority to
335 priority = int(command_tuple[2])
337 op_list = gdb.frames.return_list(list_op)
340 ff = op_list[frame_filter]
342 msg = "frame-filter '" + str(frame_filter) + "' not found."
343 raise gdb.GdbError(msg)
345 gdb.frames.set_priority(ff, priority)
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)
353 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
354 return _complete_frame_filter_name(word, printer_list)
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)
361 class ShowFrameFilterPriority(gdb.Command):
362 """GDB command to show the priority of the specified frame-filter.
364 Usage: show frame-filter priority DICTIONARY NAME
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.
372 NAME matches the name of the frame-filter to operate on.
376 super(ShowFrameFilterPriority, self).__init__("show frame-filter " \
380 def _parse_pri_arg(self, arg):
381 """Internal worker to parse a dictionary and name from a
385 arg: Tuple which contains the arguments from the command.
388 A tuple containing the dictionary, and frame filter name.
391 gdb.GdbError: An error parsing the arguments.
394 argv = gdb.string_to_argv(arg);
397 print("show frame-filter priority " \
398 "takes exactly two arguments.")
403 def get_filter_priority(self, frame_filters, name):
404 """Worker for retrieving the priority of frame_filters.
407 frame_filters: Name of frame filter dictionary.
408 name: object to select printers.
411 The priority of the frame filter.
414 gdb.GdbError: A frame filter cannot be found.
417 op_list = gdb.frames.return_list(frame_filters)
422 msg = "frame-filter '" + str(name) + "' not found."
423 raise gdb.GdbError(msg)
425 return gdb.frames.get_priority(ff)
427 def complete(self, text, word):
428 """Completion function for both frame filter dictionary, and
429 frame filter name."""
431 if text.count(" ") == 0:
432 return _complete_frame_filter_list(text, word, False)
434 printer_list = frame._return_list(text.split()[0].rstrip())
435 return _complete_frame_filter_name(word, printer_list)
437 def invoke(self, arg, from_tty):
438 command_tuple = self._parse_pri_arg(arg)
439 if command_tuple == None:
441 filter_name = command_tuple[1]
442 list_name = command_tuple[0]
444 priority = self.get_filter_priority(list_name, filter_name);
446 e = sys.exc_info()[1]
447 print("Error printing filter priority for '"+name+"':"+str(e))
449 print("Priority of filter '" + filter_name + "' in list '" \
450 + list_name + "' is: " + str(priority))
454 ShowFilterPrefixCmd()
458 SetFrameFilterPriority()
459 ShowFrameFilterPriority()