GDB (xrefs)
xmethod.py
Go to the documentation of this file.
1 # Python side of the support for xmethods.
2 # Copyright (C) 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 """Utilities for defining xmethods"""
18 
19 import gdb
20 import re
21 import sys
22 
23 
24 if sys.version_info[0] > 2:
25  # Python 3 removed basestring and long
26  basestring = str
27  long = int
28 
29 
30 class XMethod(object):
31  """Base class (or a template) for an xmethod description.
32 
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.
40 
41  Attributes:
42  name: The name of the xmethod.
43  enabled: A boolean indicating if the xmethod is enabled.
44  """
45 
46  def __init__(self, name):
47  self.name = name
48  self.enabled = True
49 
50 
51 class XMethodMatcher(object):
52  """Abstract base class for matching an xmethod.
53 
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).
59 
60  Attributes:
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.
70  """
71 
72  def __init__(self, name):
73  """
74  Args:
75  name: An identifying name for the xmethod or the group of
76  xmethods returned by the `match' method.
77  """
78  self.name = name
79  self.enabled = True
80  self.methods = None
81 
82  def match(self, class_type, method_name):
83  """Match class type and method name.
84 
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
88  returned.
89 
90  Args:
91  class_type: The class type (gdb.Type object) to match.
92  method_name: The name (string) of the method to match.
93  """
94  raise NotImplementedError("XMethodMatcher match")
95 
96 
97 class XMethodWorker(object):
98  """Base class for all xmethod workers defined in Python.
99 
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.
106 
107  Derived classes should override the 'get_arg_types', 'get_result_type'
108  and '__call__' methods.
109  """
110 
111  def get_arg_types(self):
112  """Return arguments types of an xmethod.
113 
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
118  element is returned.
119  """
120  raise NotImplementedError("XMethodWorker get_arg_types")
121 
122  def get_result_type(self, *args):
123  """Return the type of the result of the xmethod.
124 
125  Args:
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__'.
129 
130  Returns:
131  A gdb.Type object representing the type of the result of the
132  xmethod.
133  """
134  raise NotImplementedError("XMethodWorker get_result_type")
135 
136  def __call__(self, *args):
137  """Invoke the xmethod.
138 
139  Args:
140  args: Arguments to the method. Each element of the tuple is a
141  gdb.Value object. The first element is the 'this' pointer
142  value.
143 
144  Returns:
145  A gdb.Value corresponding to the value returned by the xmethod.
146  Returns 'None' if the method does not return anything.
147  """
148  raise NotImplementedError("XMethodWorker __call__")
149 
150 
152  """A utility class to implement simple xmethod mathers and workers.
153 
154  See the __init__ method below for information on how instances of this
155  class can be used.
156 
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.
162  """
163 
164  class SimpleXMethodWorker(XMethodWorker):
165  def __init__(self, method_function, arg_types):
166  self._arg_types = arg_types
167  self._method_function = method_function
168 
169  def get_arg_types(self):
170  return self._arg_types
171 
172  def __call__(self, *args):
173  return self._method_function(*args)
174 
175 
176  def __init__(self, name, class_matcher, method_matcher, method_function,
177  *arg_types):
178  """
179  Args:
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
190  objects.
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.
194  """
195  XMethodMatcher.__init__(self, name)
196  assert callable(method_function), (
197  "The 'method_function' argument to 'SimpleXMethodMatcher' "
198  "__init__ method should be a callable.")
199  self._method_function = method_function
200  self._class_matcher = class_matcher
201  self._method_matcher = method_matcher
202  self._arg_types = arg_types
203 
204  def match(self, class_type, method_name):
205  cm = re.match(self._class_matcher, str(class_type.unqualified().tag))
206  mm = re.match(self._method_matcher, method_name)
207  if cm and mm:
209  self._method_function, self._arg_types)
210 
211 
212 # A helper function for register_xmethod_matcher which returns an error
213 # object if MATCHER is not having the requisite attributes in the proper
214 # format.
215 
216 def _validate_xmethod_matcher(matcher):
217  if not hasattr(matcher, "match"):
218  return TypeError("Xmethod matcher is missing method: match")
219  if not hasattr(matcher, "name"):
220  return TypeError("Xmethod matcher is missing attribute: name")
221  if not hasattr(matcher, "enabled"):
222  return TypeError("Xmethod matcher is missing attribute: enabled")
223  if not isinstance(matcher.name, basestring):
224  return TypeError("Attribute 'name' of xmethod matcher is not a "
225  "string")
226  if matcher.name.find(";") >= 0:
227  return ValueError("Xmethod matcher name cannot contain ';' in it")
228 
229 
230 # A helper function for register_xmethod_matcher which looks up an
231 # xmethod matcher with NAME in LOCUS. Returns the index of the xmethod
232 # matcher in 'xmethods' sequence attribute of the LOCUS. If NAME is not
233 # found in LOCUS, then -1 is returned.
234 
235 def _lookup_xmethod_matcher(locus, name):
236  for i in range(0, len(locus.xmethods)):
237  if locus.xmethods[i].name == name:
238  return i
239  return -1
240 
241 
242 def register_xmethod_matcher(locus, matcher, replace=False):
243  """Registers a xmethod matcher MATCHER with a LOCUS.
244 
245  Arguments:
246  locus: The locus in which the xmethods should be registered.
247  It can be 'None' to indicate that the xmethods should be
248  registered globally. Or, it could be a gdb.Objfile or a
249  gdb.Progspace object in which the xmethods should be
250  registered.
251  matcher: The xmethod matcher to register with the LOCUS. It
252  should be an instance of 'XMethodMatcher' class.
253  replace: If True, replace any existing xmethod matcher with the
254  same name in the locus. Otherwise, if a matcher with the same name
255  exists in the locus, raise an exception.
256  """
257  err = _validate_xmethod_matcher(matcher)
258  if err:
259  raise err
260  if not locus:
261  locus = gdb
262  if locus == gdb:
263  locus_name = "global"
264  else:
265  locus_name = locus.filename
266  index = _lookup_xmethod_matcher(locus, matcher.name)
267  if index >= 0:
268  if replace:
269  del locus.xmethods[index]
270  else:
271  raise RuntimeError("Xmethod matcher already registered with "
272  "%s: %s" % (locus_name, matcher.name))
273  if gdb.parameter("verbose"):
274  gdb.write("Registering xmethod matcher '%s' with %s' ...\n")
275  locus.xmethods.insert(0, matcher)
def match(self, class_type, method_name)
Definition: xmethod.py:82
def get_result_type(self, args)
Definition: xmethod.py:122
def __init__(self, method_function, arg_types)
Definition: xmethod.py:165
def register_xmethod_matcher
Definition: xmethod.py:242
def match(self, class_type, method_name)
Definition: xmethod.py:204
Definition: value.c:65
def __init__(self, name)
Definition: xmethod.py:72
def __call__(self, args)
Definition: xmethod.py:136
def __init__(self, name)
Definition: xmethod.py:46
def _validate_xmethod_matcher(matcher)
Definition: xmethod.py:216
def _lookup_xmethod_matcher(locus, name)
Definition: xmethod.py:235
const ULONGEST const LONGEST len
Definition: target.h:309