]> Git Repo - binutils.git/blob - gdb/python/lib/gdb/command/xmethods.py
0788a81b33aaabf88046faf1841eb624d21f025c
[binutils.git] / gdb / python / lib / gdb / command / xmethods.py
1 # Xmethod commands.
2 # Copyright 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 import gdb
18 import re
19
20 """GDB commands for working with xmethods."""
21
22
23 def validate_xm_regexp(part_name, regexp):
24     try:
25         return re.compile(regexp)
26     except SyntaxError:
27         raise SyntaxError("Invalid %s regexp: %s", part_name, regexp)
28
29
30 def parse_xm_command_args(arg):
31     """Parses the arguments passed to a xmethod command.
32
33     Arguments:
34         arg: The argument string passed to a xmethod command.
35
36     Returns:
37         A 3-tuple: (<locus matching regular expression>,
38                     <matcher matching regular expression>,
39                     <name matching regular experession>)
40     """
41     argv = gdb.string_to_argv(arg)
42     argc = len(argv)
43     if argc > 2:
44         raise SyntaxError("Too many arguments to command.")
45     locus_regexp = ""
46     matcher_name_regexp = ""
47     xm_name_regexp = None
48     if argc >= 1:
49         locus_regexp = argv[0]
50     if argc == 2:
51         parts = argv[1].split(";", 1)
52         matcher_name_regexp = parts[0]
53         if len(parts) > 1:
54             xm_name_regexp = parts[1]
55     if xm_name_regexp:
56         name_re = validate_xm_regexp("xmethod name", xm_name_regexp)
57     else:
58         name_re = None
59     return (validate_xm_regexp("locus", locus_regexp),
60             validate_xm_regexp("matcher name", matcher_name_regexp),
61             name_re)
62
63
64 def get_global_method_matchers(locus_re, matcher_re):
65     """Returns a dict of matching globally registered xmethods.
66
67     Arguments:
68         locus_re: Even though only globally registered xmethods are
69                   looked up, they will be looked up only if 'global' matches
70                   LOCUS_RE.
71         matcher_re: The regular expression matching the names of xmethods.
72
73     Returns:
74         A dict of matching globally registered xmethod matchers.  The only
75         key in the dict will be 'global'.
76     """
77     locus_str = "global"
78     xm_dict = { locus_str: [] }
79     if locus_re.match("global"):
80         xm_dict[locus_str].extend(
81             [m for m in gdb.xmethods if matcher_re.match(m.name)])
82     return xm_dict
83
84
85 def get_method_matchers_in_loci(loci, locus_re, matcher_re):
86     """Returns a dict of matching registered xmethods in the LOCI.
87
88     Arguments:
89         loci: The list of loci to lookup matching xmethods in.
90         locus_re: If a locus is an objfile, then xmethod matchers will be
91                   looked up in it only if its filename matches the regular
92                   expression LOCUS_RE.  If a locus is the current progspace,
93                   then xmethod matchers will be looked up in it only if the
94                   string "progspace" matches LOCUS_RE.
95         matcher_re: The regular expression to match the xmethod matcher
96                     names.
97
98     Returns:
99         A dict of matching xmethod matchers.  The keys of the dict are the
100         filenames of the loci the xmethod matchers belong to.
101     """
102     xm_dict = {}
103     for locus in loci:
104         if isinstance(locus, gdb.Progspace):
105             if not locus_re.match('progspace'):
106                 continue
107             locus_type = "progspace"
108         else:
109             if not locus_re.match(locus.filename):
110                 continue
111             locus_type = "objfile"
112         locus_str = "%s %s" % (locus_type, locus.filename)
113         xm_dict[locus_str] = [
114             m for m in locus.xmethods if matcher_re.match(m.name)]
115     return xm_dict
116
117
118 def print_xm_info(xm_dict, name_re):
119     """Print a dictionary of xmethods."""
120     def get_status_string(m):
121         if not m.enabled:
122             return " [disabled]"
123         else:
124           return ""
125
126     if not xm_dict:
127         return
128     for locus_str in xm_dict:
129         if not xm_dict[locus_str]:
130             continue
131         print ("Xmethods in %s:" % locus_str)
132         for matcher in xm_dict[locus_str]:
133             print ("  %s%s" % (matcher.name, get_status_string(matcher)))
134             if not matcher.methods:
135                 continue
136             for m in matcher.methods:
137                 if name_re is None or name_re.match(m.name):
138                     print ("    %s%s" % (m.name, get_status_string(m)))
139
140
141 def set_xm_status1(xm_dict, name_re, status):
142     """Set the status (enabled/disabled) of a dictionary of xmethods."""
143     for locus_str, matchers in xm_dict.items():
144         for matcher in matchers:
145             if not name_re:
146                 # If the name regex is missing, then set the status of the
147                 # matcher and move on.
148                 matcher.enabled = status
149                 continue
150             if not matcher.methods:
151                 # The methods attribute could be None.  Move on.
152                 continue
153             for m in matcher.methods:
154                 if name_re.match(m.name):
155                     m.enabled = status
156
157
158 def set_xm_status(arg, status):
159     """Set the status (enabled/disabled) of xmethods matching ARG.
160     This is a helper function for enable/disable commands.  ARG is the
161     argument string passed to the commands.
162     """
163     locus_re, matcher_re, name_re = parse_xm_command_args(arg)
164     set_xm_status1(get_global_method_matchers(locus_re, matcher_re), name_re,
165                    status)
166     set_xm_status1(
167         get_method_matchers_in_loci(
168             [gdb.current_progspace()], locus_re, matcher_re),
169         name_re,
170         status)
171     set_xm_status1(
172         get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
173         name_re,
174         status)
175
176
177 class InfoXMethod(gdb.Command):
178     """GDB command to list registered xmethod matchers.
179
180     Usage: info xmethod [locus-regexp [name-regexp]]
181
182     LOCUS-REGEXP is a regular expression matching the location of the
183     xmethod matchers.  If it is omitted, all registered xmethod matchers
184     from all loci are listed.  A locus could be 'global', a regular expression
185     matching the current program space's filename, or a regular expression
186     matching filenames of objfiles.  Locus could be 'progspace' to specify that
187     only xmethods from the current progspace should be listed.
188
189     NAME-REGEXP is a regular expression matching the names of xmethod
190     matchers.  If this omitted for a specified locus, then all registered
191     xmethods in the locus are listed.  To list only a certain xmethods
192     managed by a single matcher, the name regexp can be specified as
193     matcher-name-regexp;xmethod-name-regexp.
194     """
195
196     def __init__(self):
197         super(InfoXMethod, self).__init__("info xmethod",
198                                           gdb.COMMAND_DATA)
199
200     def invoke(self, arg, from_tty):
201         locus_re, matcher_re, name_re = parse_xm_command_args(arg)
202         print_xm_info(get_global_method_matchers(locus_re, matcher_re),
203                       name_re)
204         print_xm_info(
205             get_method_matchers_in_loci(
206                 [gdb.current_progspace()], locus_re, matcher_re),
207             name_re)
208         print_xm_info(
209             get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
210             name_re)
211
212
213 class EnableXMethod(gdb.Command):
214     """GDB command to enable a specified (group of) xmethod(s).
215
216     Usage: enable xmethod [locus-regexp [name-regexp]]
217
218     LOCUS-REGEXP is a regular expression matching the location of the
219     xmethod matchers.  If it is omitted, all registered xmethods matchers
220     from all loci are enabled.  A locus could be 'global', a regular expression
221     matching the current program space's filename, or a regular expression
222     matching filenames of objfiles.  Locus could be 'progspace' to specify that
223     only xmethods from the current progspace should be enabled.
224
225     NAME-REGEXP is a regular expression matching the names of xmethods
226     within a given locus.  If this omitted for a specified locus, then all
227     registered xmethod matchers in the locus are enabled.  To enable only
228     a certain xmethods managed by a single matcher, the name regexp can be
229     specified as matcher-name-regexp;xmethod-name-regexp.
230     """
231
232     def __init__(self):
233         super(EnableXMethod, self).__init__("enable xmethod",
234                                             gdb.COMMAND_DATA)
235
236     def invoke(self, arg, from_tty):
237         set_xm_status(arg, True)
238
239
240 class DisableXMethod(gdb.Command):
241     """GDB command to disable a specified (group of) xmethod(s).
242
243     Usage: disable xmethod [locus-regexp [name-regexp]]
244
245     LOCUS-REGEXP is a regular expression matching the location of the
246     xmethod matchers.  If it is omitted, all registered xmethod matchers
247     from all loci are disabled.  A locus could be 'global', a regular
248     expression matching the current program space's filename, or a regular
249     expression filenames of objfiles. Locus could be 'progspace' to specify
250     that only xmethods from the current progspace should be disabled.
251
252     NAME-REGEXP is a regular expression matching the names of xmethods
253     within a given locus.  If this omitted for a specified locus, then all
254     registered xmethod matchers in the locus are disabled.  To disable
255     only a certain xmethods managed by a single matcher, the name regexp
256     can be specified as matcher-name-regexp;xmethod-name-regexp.
257     """
258
259     def __init__(self):
260         super(DisableXMethod, self).__init__("disable xmethod",
261                                              gdb.COMMAND_DATA)
262
263     def invoke(self, arg, from_tty):
264         set_xm_status(arg, False)
265
266
267 def register_xmethod_commands():
268     """Installs the xmethod commands."""
269     InfoXMethod()
270     EnableXMethod()
271     DisableXMethod()
272
273
274 register_xmethod_commands()
This page took 0.031531 seconds and 2 git commands to generate.