GDB (xrefs)
frame_filters.py
Go to the documentation of this file.
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
def set_enabled(filter_item, state)
Definition: frames.py:78
def get_filter_priority(self, frame_filters, name)
def _complete_frame_filter_name(word, printer_dict)
def set_priority(filter_item, priority)
Definition: frames.py:45
def return_list(name)
Definition: frames.py:90
def print_list(self, title, frame_filters, blank_line)
def _enable_parse_arg(cmd_name, arg)
def _do_enable_frame_filter(command_tuple, flag)
def get_enabled(filter_item)
Definition: frames.py:56
def _complete_frame_filter_list(text, word, all_flag)
def get_priority(filter_item)
Definition: frames.py:25