binutils-gdb/gdb/python/lib/gdb/command/xmethods.py
Siva Chandra 70afc5b72d Align behavior of xmethod commands with that of pretty-printer commands.
Currently, the xmethod commands lookup xmethod matchers in the current
progspace even if the locus regular expression matches the progspace's
filename.  Pretty printer commands do not match the current progspace's
filename.

gdb/

	* python/lib/gdb/command/xmethods.py
	(get_method_matchers_in_loci):  Lookup xmethod matchers in the
	current progspace only if the string "progspace" matches LOCUS_RE.

gdb/testsuite

	* gdb.python/py-xmethods.exp: Use "progspace" instead of the
	progspace's filename in 'info', 'enable' and 'disable' command
	tests.
2014-06-23 04:57:51 -07:00

274 lines
9.9 KiB
Python

# Xmethod commands.
# Copyright 2013-2014 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(method):
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" % matcher.name)
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.iteritems():
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()