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