Index: gdb/python/lib/gdb/command/frame_filters.py |
diff --git a/gdb/python/lib/gdb/command/frame_filters.py b/gdb/python/lib/gdb/command/frame_filters.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b04f47791622f262f7504fadc50750d69b9c1701 |
--- /dev/null |
+++ b/gdb/python/lib/gdb/command/frame_filters.py |
@@ -0,0 +1,467 @@ |
+# Frame-filter commands. |
+# Copyright (C) 2013 Free Software Foundation, Inc. |
+ |
+# This program is free software; you can redistribute it and/or modify |
+# it under the terms of the GNU General Public License as published by |
+# the Free Software Foundation; either version 3 of the License, or |
+# (at your option) any later version. |
+# |
+# This program is distributed in the hope that it will be useful, |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+# GNU General Public License for more details. |
+# |
+# You should have received a copy of the GNU General Public License |
+# along with this program. If not, see <http://www.gnu.org/licenses/>. |
+ |
+"""GDB commands for working with frame-filters.""" |
+ |
+import sys |
+import gdb |
+import copy |
+from gdb.FrameIterator import FrameIterator |
+from gdb.FrameDecorator import FrameDecorator |
+import gdb.frames |
+import itertools |
+ |
+# GDB Commands. |
+class SetFilterPrefixCmd(gdb.Command): |
+ """Prefix command for 'set' frame-filter related operations.""" |
+ |
+ def __init__(self): |
+ super(SetFilterPrefixCmd, self).__init__("set frame-filter", |
+ gdb.COMMAND_OBSCURE, |
+ gdb.COMPLETE_NONE, True) |
+ |
+class ShowFilterPrefixCmd(gdb.Command): |
+ """Prefix command for 'show' frame-filter related operations.""" |
+ def __init__(self): |
+ super(ShowFilterPrefixCmd, self).__init__("show frame-filter", |
+ gdb.COMMAND_OBSCURE, |
+ gdb.COMPLETE_NONE, True) |
+class InfoFrameFilter(gdb.Command): |
+ """List all registered Python frame-filters. |
+ |
+ Usage: info frame-filters |
+ """ |
+ |
+ def __init__(self): |
+ super(InfoFrameFilter, self).__init__("info frame-filter", |
+ gdb.COMMAND_DATA) |
+ @staticmethod |
+ def enabled_string(state): |
+ """Return "Yes" if filter is enabled, otherwise "No".""" |
+ if state: |
+ return "Yes" |
+ else: |
+ return "No" |
+ |
+ def list_frame_filters(self, frame_filters): |
+ """ Internal worker function to list and print frame filters |
+ in a dictionary. |
+ |
+ Arguments: |
+ frame_filters: The name of the dictionary, as |
+ specified by GDB user commands. |
+ """ |
+ |
+ sorted_frame_filters = sorted(frame_filters.items(), |
+ key=lambda i: gdb.frames.get_priority(i[1]), |
+ reverse=True) |
+ |
+ if len(sorted_frame_filters) == 0: |
+ print(" No frame filters registered.") |
+ else: |
+ print(" Priority Enabled Name") |
+ for frame_filter in sorted_frame_filters: |
+ name = frame_filter[0] |
+ try: |
+ priority = '{:<8}'.format( |
+ str(gdb.frames.get_priority(frame_filter[1]))) |
+ enabled = '{:<7}'.format( |
+ self.enabled_string(gdb.frames.get_enabled(frame_filter[1]))) |
+ except Exception: |
+ e = sys.exc_info()[1] |
+ print(" Error printing filter '"+name+"': "+str(e)) |
+ else: |
+ print(" %s %s %s" % (priority, enabled, name)) |
+ |
+ def print_list(self, title, filter_list, blank_line): |
+ print(title) |
+ self.list_frame_filters(filter_list) |
+ if blank_line: |
+ print("") |
+ |
+ def invoke(self, arg, from_tty): |
+ self.print_list("global frame-filters:", gdb.frame_filters, True) |
+ |
+ cp = gdb.current_progspace() |
+ self.print_list("progspace %s frame-filters:" % cp.filename, |
+ cp.frame_filters, True) |
+ |
+ for objfile in gdb.objfiles(): |
+ self.print_list("objfile %s frame-filters:" % objfile.filename, |
+ objfile.frame_filters, False) |
+ |
+# Internal enable/disable functions. |
+ |
+def _enable_parse_arg(cmd_name, arg): |
+ """ Internal worker function to take an argument from |
+ enable/disable and return a tuple of arguments. |
+ |
+ Arguments: |
+ cmd_name: Name of the command invoking this function. |
+ args: The argument as a string. |
+ |
+ Returns: |
+ A tuple containing the dictionary, and the argument, or just |
+ the dictionary in the case of "all". |
+ """ |
+ |
+ argv = gdb.string_to_argv(arg); |
+ argc = len(argv) |
+ if argv[0] == "all" and argc > 1: |
+ raise gdb.GdbError(cmd_name + ": with 'all' " \ |
+ "you may not specify a filter.") |
+ else: |
+ if argv[0] != "all" and argc != 2: |
+ raise gdb.GdbError(cmd_name + " takes exactly two arguments.") |
+ |
+ return argv |
+ |
+def _do_enable_frame_filter(command_tuple, flag): |
+ """Worker for enabling/disabling frame_filters. |
+ |
+ Arguments: |
+ command_type: A tuple with the first element being the |
+ frame filter dictionary, and the second being |
+ the frame filter name. |
+ flag: True for Enable, False for Disable. |
+ """ |
+ |
+ list_op = command_tuple[0] |
+ op_list = gdb.frames.return_list(list_op) |
+ |
+ if list_op == "all": |
+ for item in op_list: |
+ gdb.frames.set_enabled(item, flag) |
+ else: |
+ frame_filter = command_tuple[1] |
+ try: |
+ ff = op_list[frame_filter] |
+ except KeyError: |
+ msg = "frame-filter '" + str(name) + "' not found." |
+ raise gdb.GdbError(msg) |
+ |
+ gdb.frames.set_enabled(ff, flag) |
+ |
+def _complete_frame_filter_list(text, word, all_flag): |
+ """Worker for frame filter dictionary name completion. |
+ |
+ Arguments: |
+ text: The full text of the command line. |
+ word: The most recent word of the command line. |
+ all_flag: Whether to include the word "all" in completion. |
+ |
+ Returns: |
+ A list of suggested frame filter dictionary name completions |
+ from text/word analysis. This list can be empty when there |
+ are no suggestions for completion. |
+ """ |
+ if all_flag == True: |
+ filter_locations = ["all", "global", "progspace"] |
+ else: |
+ filter_locations = ["global", "progspace"] |
+ for objfile in gdb.objfiles(): |
+ filter_locations.append(objfile.filename) |
+ |
+ # If the user just asked for completions with no completion |
+ # hints, just return all the frame filter dictionaries we know |
+ # about. |
+ if (text == ""): |
+ return filter_locations |
+ |
+ # Otherwise filter on what we know. |
+ flist = filter(lambda x,y=text:x.startswith(y), filter_locations) |
+ |
+ # If we only have one completion, complete it and return it. |
+ if len(flist) == 1: |
+ flist[0] = flist[0][len(text)-len(word):] |
+ |
+ # Otherwise, return an empty list, or a list of frame filter |
+ # dictionaries that the previous filter operation returned. |
+ return flist |
+ |
+def _complete_frame_filter_name(word, printer_dict): |
+ """Worker for frame filter name completion. |
+ |
+ Arguments: |
+ |
+ word: The most recent word of the command line. |
+ |
+ printer_dict: The frame filter dictionary to search for frame |
+ filter name completions. |
+ |
+ Returns: A list of suggested frame filter name completions |
+ from word analysis of the frame filter dictionary. This list |
+ can be empty when there are no suggestions for completion. |
+ """ |
+ |
+ printer_keys = printer_dict.keys() |
+ if (word == ""): |
+ return printer_keys |
+ |
+ flist = filter(lambda x,y=word:x.startswith(y), printer_keys) |
+ return flist |
+ |
+class EnableFrameFilter(gdb.Command): |
+ """GDB command to disable the specified frame-filter. |
+ |
+ Usage: enable frame-filter enable DICTIONARY [NAME] |
+ |
+ DICTIONARY is the name of the frame filter dictionary on which to |
+ operate. If dictionary is set to "all", perform operations on all |
+ dictionaries. Named dictionaries are: "global" for the global |
+ frame filter dictionary, "progspace" for the program space's frame |
+ filter dictionary. If either all, or the two named dictionaries |
+ are not specified, the dictionary name is assumed to be the name |
+ of the object-file name. |
+ |
+ NAME matches the name of the frame-filter to operate on. If |
+ DICTIONARY is "all", NAME is ignored. |
+ """ |
+ def __init__(self): |
+ super(EnableFrameFilter, self).__init__("enable frame-filter", |
+ gdb.COMMAND_DATA) |
+ def complete(self, text, word): |
+ """Completion function for both frame filter dictionary, and |
+ frame filter name.""" |
+ if text.count(" ") == 0: |
+ return _complete_frame_filter_list(text, word, True) |
+ else: |
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip()) |
+ return _complete_frame_filter_name(word, printer_list) |
+ |
+ def invoke(self, arg, from_tty): |
+ command_tuple = _enable_parse_arg("enable frame-filter", arg) |
+ _do_enable_frame_filter(command_tuple, True) |
+ |
+ |
+class DisableFrameFilter(gdb.Command): |
+ """GDB command to disable the specified frame-filter. |
+ |
+ Usage: disable frame-filter disable DICTIONARY [NAME] |
+ |
+ DICTIONARY is the name of the frame filter dictionary on which to |
+ operate. If dictionary is set to "all", perform operations on all |
+ dictionaries. Named dictionaries are: "global" for the global |
+ frame filter dictionary, "progspace" for the program space's frame |
+ filter dictionary. If either all, or the two named dictionaries |
+ are not specified, the dictionary name is assumed to be the name |
+ of the object-file name. |
+ |
+ NAME matches the name of the frame-filter to operate on. If |
+ DICTIONARY is "all", NAME is ignored. |
+ """ |
+ def __init__(self): |
+ super(DisableFrameFilter, self).__init__("disable frame-filter", |
+ gdb.COMMAND_DATA) |
+ |
+ def complete(self, text, word): |
+ """Completion function for both frame filter dictionary, and |
+ frame filter name.""" |
+ if text.count(" ") == 0: |
+ return _complete_frame_filter_list(text, word, True) |
+ else: |
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip()) |
+ return _complete_frame_filter_name(word, printer_list) |
+ |
+ def invoke(self, arg, from_tty): |
+ command_tuple = _enable_parse_arg("disable frame-filter", arg) |
+ _do_enable_frame_filter(command_tuple, False) |
+ |
+class SetFrameFilterPriority(gdb.Command): |
+ """GDB command to set the priority of the specified frame-filter. |
+ |
+ Usage: set frame-filter priority DICTIONARY NAME PRIORITY |
+ |
+ DICTIONARY is the name of the frame filter dictionary on which to |
+ operate. Named dictionaries are: "global" for the global frame |
+ filter dictionary, "progspace" for the program space's framefilter |
+ dictionary. If either of these two are not specified, the |
+ dictionary name is assumed to be the name of the object-file name. |
+ |
+ NAME matches the name of the frame filter to operate on. |
+ |
+ PRIORITY is the an integer to assign the new priority to the frame |
+ filter. |
+ """ |
+ |
+ def __init__(self): |
+ super(SetFrameFilterPriority, self).__init__("set frame-filter " \ |
+ "priority", |
+ gdb.COMMAND_DATA) |
+ |
+ def _parse_pri_arg(self, arg): |
+ """Internal worker to parse a priority from a tuple. |
+ |
+ Arguments: |
+ arg: Tuple which contains the arguments from the command. |
+ |
+ Returns: |
+ A tuple containing the dictionary, name and priority from |
+ the arguments. |
+ |
+ Raises: |
+ gdb.GdbError: An error parsing the arguments. |
+ """ |
+ |
+ argv = gdb.string_to_argv(arg); |
+ argc = len(argv) |
+ if argc != 3: |
+ print("set frame-filter priority " \ |
+ "takes exactly three arguments.") |
+ return None |
+ |
+ return argv |
+ |
+ def _set_filter_priority(self, command_tuple): |
+ """Internal worker for setting priority of frame-filters, by |
+ parsing a tuple and calling _set_priority with the parsed |
+ tuple. |
+ |
+ Arguments: |
+ command_tuple: Tuple which contains the arguments from the |
+ command. |
+ """ |
+ |
+ list_op = command_tuple[0] |
+ frame_filter = command_tuple[1] |
+ |
+ # GDB returns arguments as a string, so convert priority to |
+ # a number. |
+ priority = int(command_tuple[2]) |
+ |
+ op_list = gdb.frames.return_list(list_op) |
+ |
+ try: |
+ ff = op_list[frame_filter] |
+ except KeyError: |
+ msg = "frame-filter '" + str(name) + "' not found." |
+ raise gdb.GdbError(msg) |
+ |
+ gdb.frames.set_priority(ff, priority) |
+ |
+ def complete(self, text, word): |
+ """Completion function for both frame filter dictionary, and |
+ frame filter name.""" |
+ if text.count(" ") == 0: |
+ return _complete_frame_filter_list(text, word, False) |
+ else: |
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip()) |
+ return _complete_frame_filter_name(word, printer_list) |
+ |
+ def invoke(self, arg, from_tty): |
+ command_tuple = self._parse_pri_arg(arg) |
+ if command_tuple != None: |
+ self._set_filter_priority(command_tuple) |
+ |
+class ShowFrameFilterPriority(gdb.Command): |
+ """GDB command to show the priority of the specified frame-filter. |
+ |
+ Usage: show frame-filter priority DICTIONARY NAME |
+ |
+ DICTIONARY is the name of the frame filter dictionary on which to |
+ operate. Named dictionaries are: "global" for the global frame |
+ filter dictionary, "progspace" for the program space's framefilter |
+ dictionary. If either of these two are not specified, the |
+ dictionary name is assumed to be the name of the object-file name. |
+ |
+ NAME matches the name of the frame-filter to operate on. |
+ """ |
+ |
+ def __init__(self): |
+ super(ShowFrameFilterPriority, self).__init__("show frame-filter " \ |
+ "priority", |
+ gdb.COMMAND_DATA) |
+ |
+ def _parse_pri_arg(self, arg): |
+ """Internal worker to parse a dictionary and name from a |
+ tuple. |
+ |
+ Arguments: |
+ arg: Tuple which contains the arguments from the command. |
+ |
+ Returns: |
+ A tuple containing the dictionary, and frame filter name. |
+ |
+ Raises: |
+ gdb.GdbError: An error parsing the arguments. |
+ """ |
+ |
+ argv = gdb.string_to_argv(arg); |
+ argc = len(argv) |
+ if argc != 2: |
+ print("show frame-filter priority " \ |
+ "takes exactly two arguments.") |
+ return None |
+ |
+ return argv |
+ |
+ def get_filter_priority(self, frame_filters, name): |
+ """Worker for retrieving the priority of frame_filters. |
+ |
+ Arguments: |
+ frame_filters: Name of frame filter dictionary. |
+ name: object to select printers. |
+ |
+ Returns: |
+ The priority of the frame filter. |
+ |
+ Raises: |
+ gdb.GdbError: A frame filter cannot be found. |
+ """ |
+ |
+ op_list = gdb.frames.return_list(frame_filters) |
+ |
+ try: |
+ ff = op_list[name] |
+ except KeyError: |
+ msg = "frame-filter '" + str(name) + "' not found." |
+ raise gdb.GdbError(msg) |
+ |
+ return gdb.frames.get_priority(ff) |
+ |
+ def complete(self, text, word): |
+ """Completion function for both frame filter dictionary, and |
+ frame filter name.""" |
+ |
+ if text.count(" ") == 0: |
+ return _complete_frame_filter_list(text, word, False) |
+ else: |
+ printer_list = frame._return_list(text.split()[0].rstrip()) |
+ return _complete_frame_filter_name(word, printer_list) |
+ |
+ def invoke(self, arg, from_tty): |
+ command_tuple = self._parse_pri_arg(arg) |
+ if command_tuple == None: |
+ return |
+ filter_name = command_tuple[1] |
+ list_name = command_tuple[0] |
+ try: |
+ priority = self.get_filter_priority(list_name, filter_name); |
+ except Exception: |
+ e = sys.exc_info()[1] |
+ print("Error printing filter priority for '"+name+"':"+str(e)) |
+ else: |
+ print("Priority of filter '" + filter_name + "' in list '" \ |
+ + list_name + "' is: " + str(priority)) |
+ |
+# Register commands |
+SetFilterPrefixCmd() |
+ShowFilterPrefixCmd() |
+InfoFrameFilter() |
+EnableFrameFilter() |
+DisableFrameFilter() |
+SetFrameFilterPriority() |
+ShowFrameFilterPriority() |