diff options
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()) |