44eb4dd88c1429188ff85916aeb080405f5fcedc
1 # Python side of the support for xmethods.
2 # Copyright (C) 2013-2021 Free Software Foundation, Inc.
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.
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.
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/>.
17 """Utilities for defining xmethods"""
24 if sys
.version_info
[0] > 2:
25 # Python 3 removed basestring and long
30 class XMethod(object):
31 """Base class (or a template) for an xmethod description.
33 Currently, the description requires only the 'name' and 'enabled'
34 attributes. Description objects are managed by 'XMethodMatcher'
35 objects (see below). Note that this is only a template for the
36 interface of the XMethodMatcher.methods objects. One could use
37 this class or choose to use an object which supports this exact same
38 interface. Also, an XMethodMatcher can choose not use it 'methods'
39 attribute. In such cases this class (or an equivalent) is not used.
42 name: The name of the xmethod.
43 enabled: A boolean indicating if the xmethod is enabled.
46 def __init__(self
, name
):
51 class XMethodMatcher(object):
52 """Abstract base class for matching an xmethod.
54 When looking for xmethods, GDB invokes the `match' method of a
55 registered xmethod matcher to match the object type and method name.
56 The `match' method in concrete classes derived from this class should
57 return an `XMethodWorker' object, or a list of `XMethodWorker'
58 objects if there is a match (see below for 'XMethodWorker' class).
61 name: The name of the matcher.
62 enabled: A boolean indicating if the matcher is enabled.
63 methods: A sequence of objects of type 'XMethod', or objects
64 which have at least the attributes of an 'XMethod' object.
65 This list is used by the 'enable'/'disable'/'info' commands to
66 enable/disable/list the xmethods registered with GDB. See
67 the 'match' method below to know how this sequence is used.
68 This attribute is None if the matcher chooses not have any
69 xmethods managed by it.
72 def __init__(self
, name
):
75 name: An identifying name for the xmethod or the group of
76 xmethods returned by the `match' method.
82 def match(self
, class_type
, method_name
):
83 """Match class type and method name.
85 In derived classes, it should return an XMethodWorker object, or a
86 sequence of 'XMethodWorker' objects. Only those xmethod workers
87 whose corresponding 'XMethod' descriptor object is enabled should be
91 class_type: The class type (gdb.Type object) to match.
92 method_name: The name (string) of the method to match.
94 raise NotImplementedError("XMethodMatcher match")
97 class XMethodWorker(object):
98 """Base class for all xmethod workers defined in Python.
100 An xmethod worker is an object which matches the method arguments, and
101 invokes the method when GDB wants it to. Internally, GDB first invokes the
102 'get_arg_types' method to perform overload resolution. If GDB selects to
103 invoke this Python xmethod, then it invokes it via the overridden
104 '__call__' method. The 'get_result_type' method is used to implement
105 'ptype' on the xmethod.
107 Derived classes should override the 'get_arg_types', 'get_result_type'
108 and '__call__' methods.
111 def get_arg_types(self
):
112 """Return arguments types of an xmethod.
114 A sequence of gdb.Type objects corresponding to the arguments of the
115 xmethod are returned. If the xmethod takes no arguments, then 'None'
116 or an empty sequence is returned. If the xmethod takes only a single
117 argument, then a gdb.Type object or a sequence with a single gdb.Type
120 raise NotImplementedError("XMethodWorker get_arg_types")
122 def get_result_type(self
, *args
):
123 """Return the type of the result of the xmethod.
126 args: Arguments to the method. Each element of the tuple is a
127 gdb.Value object. The first element is the 'this' pointer
128 value. These are the same arguments passed to '__call__'.
131 A gdb.Type object representing the type of the result of the
134 raise NotImplementedError("XMethodWorker get_result_type")
136 def __call__(self
, *args
):
137 """Invoke the xmethod.
140 args: Arguments to the method. Each element of the tuple is a
141 gdb.Value object. The first element is the 'this' pointer
145 A gdb.Value corresponding to the value returned by the xmethod.
146 Returns 'None' if the method does not return anything.
148 raise NotImplementedError("XMethodWorker __call__")
151 class SimpleXMethodMatcher(XMethodMatcher
):
152 """A utility class to implement simple xmethod mathers and workers.
154 See the __init__ method below for information on how instances of this
157 For simple classes and methods, one can choose to use this class. For
158 complex xmethods, which need to replace/implement template methods on
159 possibly template classes, one should implement their own xmethod
160 matchers and workers. See py-xmethods.py in testsuite/gdb.python
161 directory of the GDB source tree for examples.
164 class SimpleXMethodWorker(XMethodWorker
):
165 def __init__(self
, method_function
, arg_types
):
166 self
._arg
_types
= arg_types
167 self
._method
_function
= method_function
169 def get_arg_types(self
):
170 return self
._arg
_types
172 def __call__(self
, *args
):
173 return self
._method
_function
(*args
)
176 self
, name
, class_matcher
, method_matcher
, method_function
, *arg_types
180 name: Name of the xmethod matcher.
181 class_matcher: A regular expression used to match the name of the
182 class whose method this xmethod is implementing/replacing.
183 method_matcher: A regular expression used to match the name of the
184 method this xmethod is implementing/replacing.
185 method_function: A Python callable which would be called via the
186 'invoke' method of the worker returned by the objects of this
187 class. This callable should accept the object (*this) as the
188 first argument followed by the rest of the arguments to the
189 method. All arguments to this function should be gdb.Value
191 arg_types: The gdb.Type objects corresponding to the arguments that
192 this xmethod takes. It can be None, or an empty sequence,
193 or a single gdb.Type object, or a sequence of gdb.Type objects.
195 XMethodMatcher
.__init
__(self
, name
)
196 assert callable(method_function
), (
197 "The 'method_function' argument to 'SimpleXMethodMatcher' "
198 "__init__ method should be a callable."
200 self
._method
_function
= method_function
201 self
._class
_matcher
= class_matcher
202 self
._method
_matcher
= method_matcher
203 self
._arg
_types
= arg_types
205 def match(self
, class_type
, method_name
):
206 cm
= re
.match(self
._class
_matcher
, str(class_type
.unqualified().tag
))
207 mm
= re
.match(self
._method
_matcher
, method_name
)
209 return SimpleXMethodMatcher
.SimpleXMethodWorker(
210 self
._method
_function
, self
._arg
_types
214 # A helper function for register_xmethod_matcher which returns an error
215 # object if MATCHER is not having the requisite attributes in the proper
219 def _validate_xmethod_matcher(matcher
):
220 if not hasattr(matcher
, "match"):
221 return TypeError("Xmethod matcher is missing method: match")
222 if not hasattr(matcher
, "name"):
223 return TypeError("Xmethod matcher is missing attribute: name")
224 if not hasattr(matcher
, "enabled"):
225 return TypeError("Xmethod matcher is missing attribute: enabled")
226 if not isinstance(matcher
.name
, basestring
):
227 return TypeError("Attribute 'name' of xmethod matcher is not a " "string")
228 if matcher
.name
.find(";") >= 0:
229 return ValueError("Xmethod matcher name cannot contain ';' in it")
232 # A helper function for register_xmethod_matcher which looks up an
233 # xmethod matcher with NAME in LOCUS. Returns the index of the xmethod
234 # matcher in 'xmethods' sequence attribute of the LOCUS. If NAME is not
235 # found in LOCUS, then -1 is returned.
238 def _lookup_xmethod_matcher(locus
, name
):
239 for i
in range(0, len(locus
.xmethods
)):
240 if locus
.xmethods
[i
].name
== name
:
245 def register_xmethod_matcher(locus
, matcher
, replace
=False):
246 """Registers a xmethod matcher MATCHER with a LOCUS.
249 locus: The locus in which the xmethods should be registered.
250 It can be 'None' to indicate that the xmethods should be
251 registered globally. Or, it could be a gdb.Objfile or a
252 gdb.Progspace object in which the xmethods should be
254 matcher: The xmethod matcher to register with the LOCUS. It
255 should be an instance of 'XMethodMatcher' class.
256 replace: If True, replace any existing xmethod matcher with the
257 same name in the locus. Otherwise, if a matcher with the same name
258 exists in the locus, raise an exception.
260 err
= _validate_xmethod_matcher(matcher
)
266 locus_name
= "global"
268 locus_name
= locus
.filename
269 index
= _lookup_xmethod_matcher(locus
, matcher
.name
)
272 del locus
.xmethods
[index
]
275 "Xmethod matcher already registered with "
276 "%s: %s" % (locus_name
, matcher
.name
)
278 if gdb
.parameter("verbose"):
279 gdb
.write("Registering xmethod matcher '%s' with %s' ...\n")
280 locus
.xmethods
.insert(0, matcher
)
This page took 0.036023 seconds and 3 git commands to generate.