diff options
author | Siva Chandra <sivachandra@chromium.org> | 2014-05-20 06:53:04 -0700 |
---|---|---|
committer | Siva Chandra <sivachandra@chromium.org> | 2014-06-03 10:03:07 -0700 |
commit | 883964a75e8c6531f167391354f1a4d83d203988 (patch) | |
tree | 75eb5ad7ee3808a76dd561f58b6412be5c52b3a0 /gdb/testsuite/gdb.python/py-xmethods.py | |
parent | 58992dc550f2012ca04f190cb77d2d829301cb72 (diff) | |
download | gdb-883964a75e8c6531f167391354f1a4d83d203988.zip gdb-883964a75e8c6531f167391354f1a4d83d203988.tar.gz gdb-883964a75e8c6531f167391354f1a4d83d203988.tar.bz2 |
Xmethod support in Python.
* python/py-xmethods.c: New file.
* python/py-objfile.c (objfile_object): New field 'xmethods'.
(objfpy_dealloc): XDECREF on the new xmethods field.
(objfpy_new, objfile_to_objfile_object): Initialize xmethods
field.
(objfpy_get_xmethods): New function.
(objfile_getset): New entry 'xmethods'.
* python/py-progspace.c (pspace_object): New field 'xmethods'.
(pspy_dealloc): XDECREF on the new xmethods field.
(pspy_new, pspace_to_pspace_object): Initialize xmethods
field.
(pspy_get_xmethods): New function.
(pspace_getset): New entry 'xmethods'.
* python/python-internal.h: Add declarations for new functions.
* python/python.c (_initialize_python): Invoke
gdbpy_initialize_xmethods.
* python/lib/gdb/__init__.py (xmethods): New
attribute.
* python/lib/gdb/xmethod.py: New file.
* python/lib/gdb/command/xmethods.py: New file.
testuite/
* gdb.python/py-xmethods.cc: New testcase to test xmethods.
* gdb.python/py-xmethods.exp: New tests to test xmethods.
* gdb.python/py-xmethods.py: Python script supporting the
new testcase and tests.
Diffstat (limited to 'gdb/testsuite/gdb.python/py-xmethods.py')
-rw-r--r-- | gdb/testsuite/gdb.python/py-xmethods.py | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/py-xmethods.py b/gdb/testsuite/gdb.python/py-xmethods.py new file mode 100644 index 0000000..6fecf2b --- /dev/null +++ b/gdb/testsuite/gdb.python/py-xmethods.py @@ -0,0 +1,218 @@ +# Copyright 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/>. + +# This file is part of the GDB testsuite. It test the xmethods support +# in the Python extension language. + +import gdb +import re + +from gdb.xmethod import XMethod +from gdb.xmethod import XMethodMatcher, XMethodWorker +from gdb.xmethod import SimpleXMethodMatcher + + +def A_plus_A(obj, opr): + print ('From Python <A_plus_A>:') + return obj['a'] + opr['a'] + + +def plus_plus_A(obj): + print ('From Python <plus_plus_A>:') + return obj['a'] + 1 + + +def A_geta(obj): + print ('From Python <A_geta>:') + return obj['a'] + + +def A_getarrayind(obj, index): + print 'From Python <A_getarrayind>:' + return obj['array'][index] + + +type_A = gdb.parse_and_eval('(dop::A *) 0').type.target() +type_B = gdb.parse_and_eval('(dop::B *) 0').type.target() +type_int = gdb.parse_and_eval('(int *) 0').type.target() + + +# The E class matcher and worker test two things: +# 1. xmethod returning None. +# 2. Matcher returning a list of workers. + +class E_method_char_worker(XMethodWorker): + def __init__(self): + pass + + def get_arg_types(self): + return gdb.lookup_type('char') + + def __call__(self, obj, arg): + print 'From Python <E_method_char>' + return None + + +class E_method_int_worker(XMethodWorker): + def __init__(self): + pass + + def get_arg_types(self): + return gdb.lookup_type('int') + + def __call__(self, obj, arg): + print 'From Python <E_method_int>' + return None + + +class E_method_matcher(XMethodMatcher): + def __init__(self): + XMethodMatcher.__init__(self, 'E_methods') + self.methods = [XMethod('method_int'), XMethod('method_char')] + + def match(self, class_type, method_name): + class_tag = class_type.unqualified().tag + if not re.match('^dop::E$', class_tag): + return None + if not re.match('^method$', method_name): + return None + workers = [] + if self.methods[0].enabled: + workers.append(E_method_int_worker()) + if self.methods[1].enabled: + workers.append(E_method_char_worker()) + return workers + + +# The G class method matcher and worker illustrate how to write +# xmethod matchers and workers for template classes and template +# methods. + +class G_size_diff_worker(XMethodWorker): + def __init__(self, class_template_type, method_template_type): + self._class_template_type = class_template_type + self._method_template_type = method_template_type + + def get_arg_types(self): + pass + + def __call__(self, obj): + print ('From Python G<>::size_diff()') + return (self._method_template_type.sizeof - + self._class_template_type.sizeof) + + +class G_size_mul_worker(XMethodWorker): + def __init__(self, class_template_type, method_template_val): + self._class_template_type = class_template_type + self._method_template_val = method_template_val + + def get_arg_types(self): + pass + + def __call__(self, obj): + print ('From Python G<>::size_mul()') + return self._class_template_type.sizeof * self._method_template_val + + +class G_mul_worker(XMethodWorker): + def __init__(self, class_template_type, method_template_type): + self._class_template_type = class_template_type + self._method_template_type = method_template_type + + def get_arg_types(self): + return self._method_template_type + + def __call__(self, obj, arg): + print ('From Python G<>::mul()') + return obj['t'] * arg + + +class G_methods_matcher(XMethodMatcher): + def __init__(self): + XMethodMatcher.__init__(self, 'G_methods') + self.methods = [XMethod('size_diff'), + XMethod('size_mul'), + XMethod('mul')] + + def _is_enabled(self, name): + for method in self.methods: + if method.name == name and method.enabled: + return True + + def match(self, class_type, method_name): + class_tag = class_type.unqualified().tag + if not re.match('^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', + class_tag): + return None + t_name = class_tag[7:-1] + try: + t_type = gdb.lookup_type(t_name) + except gdb.error: + return None + if re.match('^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name): + if not self._is_enabled('size_diff'): + return None + t1_name = method_name[10:-1] + try: + t1_type = gdb.lookup_type(t1_name) + return G_size_diff_worker(t_type, t1_type) + except gdb.error: + return None + if re.match('^size_mul<[ ]*[0-9]+[ ]*>$', method_name): + if not self._is_enabled('size_mul'): + return None + m_val = int(method_name[9:-1]) + return G_size_mul_worker(t_type, m_val) + if re.match('^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name): + if not self._is_enabled('mul'): + return None + t1_name = method_name[4:-1] + try: + t1_type = gdb.lookup_type(t1_name) + return G_mul_worker(t_type, t1_type) + except gdb.error: + return None + + +global_dm_list = [ + SimpleXMethodMatcher('A_plus_A', + '^dop::A$', + 'operator\+', + A_plus_A, + # This is a replacement, hence match the arg type + # exactly! + type_A.const().reference()), + SimpleXMethodMatcher('plus_plus_A', + '^dop::A$', + 'operator\+\+', + plus_plus_A), + SimpleXMethodMatcher('A_geta', + '^dop::A$', + '^geta$', + A_geta), + SimpleXMethodMatcher('A_getarrayind', + '^dop::A$', + '^getarrayind$', + A_getarrayind, + type_int), +] + +for matcher in global_dm_list: + gdb.xmethod.register_xmethod_matcher(gdb, matcher) +gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), + G_methods_matcher()) +gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), + E_method_matcher()) |