summaryrefslogtreecommitdiff
path: root/share/gdb/python/gdb/command/xmethods.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/gdb/python/gdb/command/xmethods.py')
-rw-r--r--share/gdb/python/gdb/command/xmethods.py274
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()