GDB (xrefs)
Loading...
Searching...
No Matches
xmethod.py
Go to the documentation of this file.
1# Python side of the support for xmethods.
2# Copyright (C) 2013-2023 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"""Utilities for defining xmethods"""
18
19import gdb
20import re
21
22
23class XMethod(object):
24 """Base class (or a template) for an xmethod description.
25
26 Currently, the description requires only the 'name' and 'enabled'
27 attributes. Description objects are managed by 'XMethodMatcher'
28 objects (see below). Note that this is only a template for the
29 interface of the XMethodMatcher.methods objects. One could use
30 this class or choose to use an object which supports this exact same
31 interface. Also, an XMethodMatcher can choose not use it 'methods'
32 attribute. In such cases this class (or an equivalent) is not used.
33
34 Attributes:
35 name: The name of the xmethod.
36 enabled: A boolean indicating if the xmethod is enabled.
37 """
38
39 def __init__(self, name):
40 self.name = name
41 self.enabled = True
42
43
44class XMethodMatcher(object):
45 """Abstract base class for matching an xmethod.
46
47 When looking for xmethods, GDB invokes the `match' method of a
48 registered xmethod matcher to match the object type and method name.
49 The `match' method in concrete classes derived from this class should
50 return an `XMethodWorker' object, or a list of `XMethodWorker'
51 objects if there is a match (see below for 'XMethodWorker' class).
52
53 Attributes:
54 name: The name of the matcher.
55 enabled: A boolean indicating if the matcher is enabled.
56 methods: A sequence of objects of type 'XMethod', or objects
57 which have at least the attributes of an 'XMethod' object.
58 This list is used by the 'enable'/'disable'/'info' commands to
59 enable/disable/list the xmethods registered with GDB. See
60 the 'match' method below to know how this sequence is used.
61 This attribute is None if the matcher chooses not have any
62 xmethods managed by it.
63 """
64
65 def __init__(self, name):
66 """
67 Args:
68 name: An identifying name for the xmethod or the group of
69 xmethods returned by the `match' method.
70 """
71 self.name = name
72 self.enabled = True
73 self.methods = None
74
75 def match(self, class_type, method_name):
76 """Match class type and method name.
77
78 In derived classes, it should return an XMethodWorker object, or a
79 sequence of 'XMethodWorker' objects. Only those xmethod workers
80 whose corresponding 'XMethod' descriptor object is enabled should be
81 returned.
82
83 Args:
84 class_type: The class type (gdb.Type object) to match.
85 method_name: The name (string) of the method to match.
86 """
87 raise NotImplementedError("XMethodMatcher match")
88
89
90class XMethodWorker(object):
91 """Base class for all xmethod workers defined in Python.
92
93 An xmethod worker is an object which matches the method arguments, and
94 invokes the method when GDB wants it to. Internally, GDB first invokes the
95 'get_arg_types' method to perform overload resolution. If GDB selects to
96 invoke this Python xmethod, then it invokes it via the overridden
97 '__call__' method. The 'get_result_type' method is used to implement
98 'ptype' on the xmethod.
99
100 Derived classes should override the 'get_arg_types', 'get_result_type'
101 and '__call__' methods.
102 """
103
104 def get_arg_types(self):
105 """Return arguments types of an xmethod.
106
107 A sequence of gdb.Type objects corresponding to the arguments of the
108 xmethod are returned. If the xmethod takes no arguments, then 'None'
109 or an empty sequence is returned. If the xmethod takes only a single
110 argument, then a gdb.Type object or a sequence with a single gdb.Type
111 element is returned.
112 """
113 raise NotImplementedError("XMethodWorker get_arg_types")
114
115 def get_result_type(self, *args):
116 """Return the type of the result of the xmethod.
117
118 Args:
119 args: Arguments to the method. Each element of the tuple is a
120 gdb.Value object. The first element is the 'this' pointer
121 value. These are the same arguments passed to '__call__'.
122
123 Returns:
124 A gdb.Type object representing the type of the result of the
125 xmethod.
126 """
127 raise NotImplementedError("XMethodWorker get_result_type")
128
129 def __call__(self, *args):
130 """Invoke the xmethod.
131
132 Args:
133 args: Arguments to the method. Each element of the tuple is a
134 gdb.Value object. The first element is the 'this' pointer
135 value.
136
137 Returns:
138 A gdb.Value corresponding to the value returned by the xmethod.
139 Returns 'None' if the method does not return anything.
140 """
141 raise NotImplementedError("XMethodWorker __call__")
142
143
145 """A utility class to implement simple xmethod mathers and workers.
146
147 See the __init__ method below for information on how instances of this
148 class can be used.
149
150 For simple classes and methods, one can choose to use this class. For
151 complex xmethods, which need to replace/implement template methods on
152 possibly template classes, one should implement their own xmethod
153 matchers and workers. See py-xmethods.py in testsuite/gdb.python
154 directory of the GDB source tree for examples.
155 """
156
157 class SimpleXMethodWorker(XMethodWorker):
158 def __init__(self, method_function, arg_types):
159 self._arg_types = arg_types
160 self._method_function = method_function
161
162 def get_arg_types(self):
163 return self._arg_types
164
165 def __call__(self, *args):
166 return self._method_function(*args)
167
169 self, name, class_matcher, method_matcher, method_function, *arg_types
170 ):
171 """
172 Args:
173 name: Name of the xmethod matcher.
174 class_matcher: A regular expression used to match the name of the
175 class whose method this xmethod is implementing/replacing.
176 method_matcher: A regular expression used to match the name of the
177 method this xmethod is implementing/replacing.
178 method_function: A Python callable which would be called via the
179 'invoke' method of the worker returned by the objects of this
180 class. This callable should accept the object (*this) as the
181 first argument followed by the rest of the arguments to the
182 method. All arguments to this function should be gdb.Value
183 objects.
184 arg_types: The gdb.Type objects corresponding to the arguments that
185 this xmethod takes. It can be None, or an empty sequence,
186 or a single gdb.Type object, or a sequence of gdb.Type objects.
187 """
188 XMethodMatcher.__init__(self, name)
189 assert callable(method_function), (
190 "The 'method_function' argument to 'SimpleXMethodMatcher' "
191 "__init__ method should be a callable."
192 )
193 self._method_function = method_function
194 self._class_matcher = class_matcher
195 self._method_matcher = method_matcher
196 self._arg_types = arg_types
197
198 def match(self, class_type, method_name):
199 cm = re.match(self._class_matcher, str(class_type.unqualified().tag))
200 mm = re.match(self._method_matcher, method_name)
201 if cm and mm:
204 )
205
206
207# A helper function for register_xmethod_matcher which returns an error
208# object if MATCHER is not having the requisite attributes in the proper
209# format.
210
211
212def _validate_xmethod_matcher(matcher):
213 if not hasattr(matcher, "match"):
214 return TypeError("Xmethod matcher is missing method: match")
215 if not hasattr(matcher, "name"):
216 return TypeError("Xmethod matcher is missing attribute: name")
217 if not hasattr(matcher, "enabled"):
218 return TypeError("Xmethod matcher is missing attribute: enabled")
219 if not isinstance(matcher.name, str):
220 return TypeError("Attribute 'name' of xmethod matcher is not a " "string")
221 if matcher.name.find(";") >= 0:
222 return ValueError("Xmethod matcher name cannot contain ';' in it")
223
224
225# A helper function for register_xmethod_matcher which looks up an
226# xmethod matcher with NAME in LOCUS. Returns the index of the xmethod
227# matcher in 'xmethods' sequence attribute of the LOCUS. If NAME is not
228# found in LOCUS, then -1 is returned.
229
230
231def _lookup_xmethod_matcher(locus, name):
232 for i in range(0, len(locus.xmethods)):
233 if locus.xmethods[i].name == name:
234 return i
235 return -1
236
237
238def register_xmethod_matcher(locus, matcher, replace=False):
239 """Registers a xmethod matcher MATCHER with a LOCUS.
240
241 Arguments:
242 locus: The locus in which the xmethods should be registered.
243 It can be 'None' to indicate that the xmethods should be
244 registered globally. Or, it could be a gdb.Objfile or a
245 gdb.Progspace object in which the xmethods should be
246 registered.
247 matcher: The xmethod matcher to register with the LOCUS. It
248 should be an instance of 'XMethodMatcher' class.
249 replace: If True, replace any existing xmethod matcher with the
250 same name in the locus. Otherwise, if a matcher with the same name
251 exists in the locus, raise an exception.
252 """
253 err = _validate_xmethod_matcher(matcher)
254 if err:
255 raise err
256 if not locus:
257 locus = gdb
258 if locus == gdb:
259 locus_name = "global"
260 else:
261 locus_name = locus.filename
262 index = _lookup_xmethod_matcher(locus, matcher.name)
263 if index >= 0:
264 if replace:
265 del locus.xmethods[index]
266 else:
267 raise RuntimeError(
268 "Xmethod matcher already registered with "
269 "%s: %s" % (locus_name, matcher.name)
270 )
271 if gdb.parameter("verbose"):
272 gdb.write("Registering xmethod matcher '%s' with %s' ...\n")
273 locus.xmethods.insert(0, matcher)
__init__(self, method_function, arg_types)
Definition xmethod.py:158
__init__(self, name, class_matcher, method_matcher, method_function, *arg_types)
Definition xmethod.py:170
match(self, class_type, method_name)
Definition xmethod.py:198
match(self, class_type, method_name)
Definition xmethod.py:75
get_result_type(self, *args)
Definition xmethod.py:115
__call__(self, *args)
Definition xmethod.py:129
__init__(self, name)
Definition xmethod.py:39
_lookup_xmethod_matcher(locus, name)
Definition xmethod.py:231
register_xmethod_matcher(locus, matcher, replace=False)
Definition xmethod.py:238
_validate_xmethod_matcher(matcher)
Definition xmethod.py:212
Definition value.h:90