diff options
Diffstat (limited to 'share/gdb/python/gdb/command/xmethods.py')
-rw-r--r-- | share/gdb/python/gdb/command/xmethods.py | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/share/gdb/python/gdb/command/xmethods.py b/share/gdb/python/gdb/command/xmethods.py new file mode 100644 index 0000000..0788a81 --- /dev/null +++ b/share/gdb/python/gdb/command/xmethods.py @@ -0,0 +1,274 @@ +# Xmethod commands. +# Copyright 2013-2015 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/>. + +import gdb +import re + +"""GDB commands for working with xmethods.""" + + +def validate_xm_regexp(part_name, regexp): + try: + return re.compile(regexp) + except SyntaxError: + raise SyntaxError("Invalid %s regexp: %s", part_name, regexp) + + +def parse_xm_command_args(arg): + """Parses the arguments passed to a xmethod command. + + Arguments: + arg: The argument string passed to a xmethod command. + + Returns: + A 3-tuple: (<locus matching regular expression>, + <matcher matching regular expression>, + <name matching regular experession>) + """ + argv = gdb.string_to_argv(arg) + argc = len(argv) + if argc > 2: + raise SyntaxError("Too many arguments to command.") + locus_regexp = "" + matcher_name_regexp = "" + xm_name_regexp = None + if argc >= 1: + locus_regexp = argv[0] + if argc == 2: + parts = argv[1].split(";", 1) + matcher_name_regexp = parts[0] + if len(parts) > 1: + xm_name_regexp = parts[1] + if xm_name_regexp: + name_re = validate_xm_regexp("xmethod name", xm_name_regexp) + else: + name_re = None + return (validate_xm_regexp("locus", locus_regexp), + validate_xm_regexp("matcher name", matcher_name_regexp), + name_re) + + +def get_global_method_matchers(locus_re, matcher_re): + """Returns a dict of matching globally registered xmethods. + + Arguments: + locus_re: Even though only globally registered xmethods are + looked up, they will be looked up only if 'global' matches + LOCUS_RE. + matcher_re: The regular expression matching the names of xmethods. + + Returns: + A dict of matching globally registered xmethod matchers. The only + key in the dict will be 'global'. + """ + locus_str = "global" + xm_dict = { locus_str: [] } + if locus_re.match("global"): + xm_dict[locus_str].extend( + [m for m in gdb.xmethods if matcher_re.match(m.name)]) + return xm_dict + + +def get_method_matchers_in_loci(loci, locus_re, matcher_re): + """Returns a dict of matching registered xmethods in the LOCI. + + Arguments: + loci: The list of loci to lookup matching xmethods in. + locus_re: If a locus is an objfile, then xmethod matchers will be + looked up in it only if its filename matches the regular + expression LOCUS_RE. If a locus is the current progspace, + then xmethod matchers will be looked up in it only if the + string "progspace" matches LOCUS_RE. + matcher_re: The regular expression to match the xmethod matcher + names. + + Returns: + A dict of matching xmethod matchers. The keys of the dict are the + filenames of the loci the xmethod matchers belong to. + """ + xm_dict = {} + for locus in loci: + if isinstance(locus, gdb.Progspace): + if not locus_re.match('progspace'): + continue + locus_type = "progspace" + else: + if not locus_re.match(locus.filename): + continue + locus_type = "objfile" + locus_str = "%s %s" % (locus_type, locus.filename) + xm_dict[locus_str] = [ + m for m in locus.xmethods if matcher_re.match(m.name)] + return xm_dict + + +def print_xm_info(xm_dict, name_re): + """Print a dictionary of xmethods.""" + def get_status_string(m): + if not m.enabled: + return " [disabled]" + else: + return "" + + if not xm_dict: + return + for locus_str in xm_dict: + if not xm_dict[locus_str]: + continue + print ("Xmethods in %s:" % locus_str) + for matcher in xm_dict[locus_str]: + print (" %s%s" % (matcher.name, get_status_string(matcher))) + if not matcher.methods: + continue + for m in matcher.methods: + if name_re is None or name_re.match(m.name): + print (" %s%s" % (m.name, get_status_string(m))) + + +def set_xm_status1(xm_dict, name_re, status): + """Set the status (enabled/disabled) of a dictionary of xmethods.""" + for locus_str, matchers in xm_dict.items(): + for matcher in matchers: + if not name_re: + # If the name regex is missing, then set the status of the + # matcher and move on. + matcher.enabled = status + continue + if not matcher.methods: + # The methods attribute could be None. Move on. + continue + for m in matcher.methods: + if name_re.match(m.name): + m.enabled = status + + +def set_xm_status(arg, status): + """Set the status (enabled/disabled) of xmethods matching ARG. + This is a helper function for enable/disable commands. ARG is the + argument string passed to the commands. + """ + locus_re, matcher_re, name_re = parse_xm_command_args(arg) + set_xm_status1(get_global_method_matchers(locus_re, matcher_re), name_re, + status) + set_xm_status1( + get_method_matchers_in_loci( + [gdb.current_progspace()], locus_re, matcher_re), + name_re, + status) + set_xm_status1( + get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), + name_re, + status) + + +class InfoXMethod(gdb.Command): + """GDB command to list registered xmethod matchers. + + Usage: info xmethod [locus-regexp [name-regexp]] + + LOCUS-REGEXP is a regular expression matching the location of the + xmethod matchers. If it is omitted, all registered xmethod matchers + from all loci are listed. A locus could be 'global', a regular expression + matching the current program space's filename, or a regular expression + matching filenames of objfiles. Locus could be 'progspace' to specify that + only xmethods from the current progspace should be listed. + + NAME-REGEXP is a regular expression matching the names of xmethod + matchers. If this omitted for a specified locus, then all registered + xmethods in the locus are listed. To list only a certain xmethods + managed by a single matcher, the name regexp can be specified as + matcher-name-regexp;xmethod-name-regexp. + """ + + def __init__(self): + super(InfoXMethod, self).__init__("info xmethod", + gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + locus_re, matcher_re, name_re = parse_xm_command_args(arg) + print_xm_info(get_global_method_matchers(locus_re, matcher_re), + name_re) + print_xm_info( + get_method_matchers_in_loci( + [gdb.current_progspace()], locus_re, matcher_re), + name_re) + print_xm_info( + get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re), + name_re) + + +class EnableXMethod(gdb.Command): + """GDB command to enable a specified (group of) xmethod(s). + + Usage: enable xmethod [locus-regexp [name-regexp]] + + LOCUS-REGEXP is a regular expression matching the location of the + xmethod matchers. If it is omitted, all registered xmethods matchers + from all loci are enabled. A locus could be 'global', a regular expression + matching the current program space's filename, or a regular expression + matching filenames of objfiles. Locus could be 'progspace' to specify that + only xmethods from the current progspace should be enabled. + + NAME-REGEXP is a regular expression matching the names of xmethods + within a given locus. If this omitted for a specified locus, then all + registered xmethod matchers in the locus are enabled. To enable only + a certain xmethods managed by a single matcher, the name regexp can be + specified as matcher-name-regexp;xmethod-name-regexp. + """ + + def __init__(self): + super(EnableXMethod, self).__init__("enable xmethod", + gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + set_xm_status(arg, True) + + +class DisableXMethod(gdb.Command): + """GDB command to disable a specified (group of) xmethod(s). + + Usage: disable xmethod [locus-regexp [name-regexp]] + + LOCUS-REGEXP is a regular expression matching the location of the + xmethod matchers. If it is omitted, all registered xmethod matchers + from all loci are disabled. A locus could be 'global', a regular + expression matching the current program space's filename, or a regular + expression filenames of objfiles. Locus could be 'progspace' to specify + that only xmethods from the current progspace should be disabled. + + NAME-REGEXP is a regular expression matching the names of xmethods + within a given locus. If this omitted for a specified locus, then all + registered xmethod matchers in the locus are disabled. To disable + only a certain xmethods managed by a single matcher, the name regexp + can be specified as matcher-name-regexp;xmethod-name-regexp. + """ + + def __init__(self): + super(DisableXMethod, self).__init__("disable xmethod", + gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + set_xm_status(arg, False) + + +def register_xmethod_commands(): + """Installs the xmethod commands.""" + InfoXMethod() + EnableXMethod() + DisableXMethod() + + +register_xmethod_commands() |