py-xmethods.py revision 1.1
1# Copyright 2014-2015 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This file is part of the GDB testsuite. It test the xmethods support 17# in the Python extension language. 18 19import gdb 20import re 21 22from gdb.xmethod import XMethod 23from gdb.xmethod import XMethodMatcher, XMethodWorker 24from gdb.xmethod import SimpleXMethodMatcher 25 26 27def A_plus_A(obj, opr): 28 print('From Python <A_plus_A>:') 29 return obj['a'] + opr['a'] 30 31 32def plus_plus_A(obj): 33 print('From Python <plus_plus_A>:') 34 return obj['a'] + 1 35 36 37def A_geta(obj): 38 print('From Python <A_geta>:') 39 return obj['a'] 40 41 42def A_getarrayind(obj, index): 43 print('From Python <A_getarrayind>:') 44 return obj['array'][index] 45 46 47type_A = gdb.parse_and_eval('(dop::A *) 0').type.target() 48type_B = gdb.parse_and_eval('(dop::B *) 0').type.target() 49type_int = gdb.parse_and_eval('(int *) 0').type.target() 50 51 52# The E class matcher and worker test two things: 53# 1. xmethod returning None. 54# 2. Matcher returning a list of workers. 55 56class E_method_char_worker(XMethodWorker): 57 def __init__(self): 58 pass 59 60 def get_arg_types(self): 61 return gdb.lookup_type('char') 62 63 def get_result_type(self, obj, arg): 64 return gdb.lookup_type('void') 65 66 def __call__(self, obj, arg): 67 print('From Python <E_method_char>') 68 return None 69 70 71class E_method_int_worker(XMethodWorker): 72 def __init__(self): 73 pass 74 75 def get_arg_types(self): 76 return gdb.lookup_type('int') 77 78 # Note: get_result_type method elided on purpose 79 80 def __call__(self, obj, arg): 81 print('From Python <E_method_int>') 82 return None 83 84 85class E_method_matcher(XMethodMatcher): 86 def __init__(self): 87 XMethodMatcher.__init__(self, 'E_methods') 88 self.methods = [XMethod('method_int'), XMethod('method_char')] 89 90 def match(self, class_type, method_name): 91 class_tag = class_type.unqualified().tag 92 if not re.match('^dop::E$', class_tag): 93 return None 94 if not re.match('^method$', method_name): 95 return None 96 workers = [] 97 if self.methods[0].enabled: 98 workers.append(E_method_int_worker()) 99 if self.methods[1].enabled: 100 workers.append(E_method_char_worker()) 101 return workers 102 103 104# The G class method matcher and worker illustrate how to write 105# xmethod matchers and workers for template classes and template 106# methods. 107 108class G_size_diff_worker(XMethodWorker): 109 def __init__(self, class_template_type, method_template_type): 110 self._class_template_type = class_template_type 111 self._method_template_type = method_template_type 112 113 def get_arg_types(self): 114 pass 115 116 def __call__(self, obj): 117 print('From Python G<>::size_diff()') 118 return (self._method_template_type.sizeof - 119 self._class_template_type.sizeof) 120 121 122class G_size_mul_worker(XMethodWorker): 123 def __init__(self, class_template_type, method_template_val): 124 self._class_template_type = class_template_type 125 self._method_template_val = method_template_val 126 127 def get_arg_types(self): 128 pass 129 130 def __call__(self, obj): 131 print('From Python G<>::size_mul()') 132 return self._class_template_type.sizeof * self._method_template_val 133 134 135class G_mul_worker(XMethodWorker): 136 def __init__(self, class_template_type, method_template_type): 137 self._class_template_type = class_template_type 138 self._method_template_type = method_template_type 139 140 def get_arg_types(self): 141 return self._method_template_type 142 143 def __call__(self, obj, arg): 144 print('From Python G<>::mul()') 145 return obj['t'] * arg 146 147 148class G_methods_matcher(XMethodMatcher): 149 def __init__(self): 150 XMethodMatcher.__init__(self, 'G_methods') 151 self.methods = [XMethod('size_diff'), 152 XMethod('size_mul'), 153 XMethod('mul')] 154 155 def _is_enabled(self, name): 156 for method in self.methods: 157 if method.name == name and method.enabled: 158 return True 159 160 def match(self, class_type, method_name): 161 class_tag = class_type.unqualified().tag 162 if not re.match('^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', 163 class_tag): 164 return None 165 t_name = class_tag[7:-1] 166 try: 167 t_type = gdb.lookup_type(t_name) 168 except gdb.error: 169 return None 170 if re.match('^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name): 171 if not self._is_enabled('size_diff'): 172 return None 173 t1_name = method_name[10:-1] 174 try: 175 t1_type = gdb.lookup_type(t1_name) 176 return G_size_diff_worker(t_type, t1_type) 177 except gdb.error: 178 return None 179 if re.match('^size_mul<[ ]*[0-9]+[ ]*>$', method_name): 180 if not self._is_enabled('size_mul'): 181 return None 182 m_val = int(method_name[9:-1]) 183 return G_size_mul_worker(t_type, m_val) 184 if re.match('^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name): 185 if not self._is_enabled('mul'): 186 return None 187 t1_name = method_name[4:-1] 188 try: 189 t1_type = gdb.lookup_type(t1_name) 190 return G_mul_worker(t_type, t1_type) 191 except gdb.error: 192 return None 193 194 195global_dm_list = [ 196 SimpleXMethodMatcher('A_plus_A', 197 '^dop::A$', 198 'operator\+', 199 A_plus_A, 200 # This is a replacement, hence match the arg type 201 # exactly! 202 type_A.const().reference()), 203 SimpleXMethodMatcher('plus_plus_A', 204 '^dop::A$', 205 'operator\+\+', 206 plus_plus_A), 207 SimpleXMethodMatcher('A_geta', 208 '^dop::A$', 209 '^geta$', 210 A_geta), 211 SimpleXMethodMatcher('A_getarrayind', 212 '^dop::A$', 213 '^getarrayind$', 214 A_getarrayind, 215 type_int), 216] 217 218for matcher in global_dm_list: 219 gdb.xmethod.register_xmethod_matcher(gdb, matcher) 220gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), 221 G_methods_matcher()) 222gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), 223 E_method_matcher()) 224