1# Copyright (C) 2008-2019 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 tests python pretty 17# printers. 18 19import re 20import gdb 21 22def _iterator (pointer, len): 23 start = pointer 24 end = pointer + len 25 while pointer != end: 26 yield ('[%d]' % int (pointer - start), pointer.dereference()) 27 pointer += 1 28 29# Same as _iterator but can be told to raise an exception. 30def _iterator_except (pointer, len): 31 start = pointer 32 end = pointer + len 33 while pointer != end: 34 if exception_flag: 35 raise gdb.MemoryError ('hi bob') 36 yield ('[%d]' % int (pointer - start), pointer.dereference()) 37 pointer += 1 38 39# Test returning a Value from a printer. 40class string_print (object): 41 def __init__(self, val): 42 self.val = val 43 44 def to_string(self): 45 return self.val['whybother']['contents'] 46 47# Test a class-based printer. 48class ContainerPrinter (object): 49 50 def __init__(self, val): 51 self.val = val 52 53 def to_string(self): 54 return 'container %s with %d elements' % (self.val['name'], self.val['len']) 55 56 def children(self): 57 return _iterator(self.val['elements'], self.val['len']) 58 59# Treats a container as array. 60class ArrayPrinter (object): 61 def __init__(self, val): 62 self.val = val 63 64 def to_string(self): 65 return 'array %s with %d elements' % (self.val['name'], self.val['len']) 66 67 def children(self): 68 return _iterator(self.val['elements'], self.val['len']) 69 70 def display_hint (self): 71 return 'array' 72 73# Flag to make NoStringContainerPrinter throw an exception. 74exception_flag = False 75 76# Test a printer where to_string is None 77class NoStringContainerPrinter (object): 78 def __init__(self, val): 79 self.val = val 80 81 def to_string(self): 82 return None 83 84 def children(self): 85 return _iterator_except (self.val['elements'], self.val['len']) 86 87# See ToStringReturnsValueWrapper. 88class ToStringReturnsValueInner: 89 90 def __init__(self, val): 91 self.val = val 92 93 def to_string(self): 94 return 'Inner to_string {}'.format(int(self.val['val'])) 95 96# Test a printer that returns a gdb.Value in its to_string. That gdb.Value 97# also has its own pretty-printer. 98class ToStringReturnsValueWrapper: 99 100 def __init__(self, val): 101 self.val = val 102 103 def to_string(self): 104 return self.val['inner'] 105 106class pp_s (object): 107 def __init__(self, val): 108 self.val = val 109 110 def to_string(self): 111 a = self.val["a"] 112 b = self.val["b"] 113 if a.address != b: 114 raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b))) 115 return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 116 117class pp_ss (object): 118 def __init__(self, val): 119 self.val = val 120 121 def to_string(self): 122 return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 123 124class pp_sss (object): 125 def __init__(self, val): 126 self.val = val 127 128 def to_string(self): 129 return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">" 130 131class pp_multiple_virtual (object): 132 def __init__ (self, val): 133 self.val = val 134 135 def to_string (self): 136 return "pp value variable is: " + str (self.val['value']) 137 138class pp_vbase1 (object): 139 def __init__ (self, val): 140 self.val = val 141 142 def to_string (self): 143 return "pp class name: " + self.val.type.tag 144 145class pp_nullstr (object): 146 def __init__(self, val): 147 self.val = val 148 149 def to_string(self): 150 return self.val['s'].string(gdb.target_charset()) 151 152class pp_ns (object): 153 "Print a std::basic_string of some kind" 154 155 def __init__(self, val): 156 self.val = val 157 158 def to_string(self): 159 len = self.val['length'] 160 return self.val['null_str'].string (gdb.target_charset(), length = len) 161 162 def display_hint (self): 163 return 'string' 164 165pp_ls_encoding = None 166 167class pp_ls (object): 168 "Print a std::basic_string of some kind" 169 170 def __init__(self, val): 171 self.val = val 172 173 def to_string(self): 174 length = self.val['len'] 175 if pp_ls_encoding is not None: 176 if length >= 0: 177 return self.val['lazy_str'].lazy_string( 178 encoding = pp_ls_encoding, 179 length = length) 180 else: 181 return self.val['lazy_str'].lazy_string( 182 encoding = pp_ls_encoding) 183 else: 184 if length >= 0: 185 return self.val['lazy_str'].lazy_string(length = length) 186 else: 187 return self.val['lazy_str'].lazy_string() 188 189 def display_hint (self): 190 return 'string' 191 192class pp_hint_error (object): 193 "Throw error from display_hint" 194 195 def __init__(self, val): 196 self.val = val 197 198 def to_string(self): 199 return 'hint_error_val' 200 201 def display_hint (self): 202 raise Exception("hint failed") 203 204class pp_children_as_list (object): 205 "Throw error from display_hint" 206 207 def __init__(self, val): 208 self.val = val 209 210 def to_string(self): 211 return 'children_as_list_val' 212 213 def children (self): 214 return [('one', 1)] 215 216class pp_outer (object): 217 "Print struct outer" 218 219 def __init__ (self, val): 220 self.val = val 221 222 def to_string (self): 223 return "x = %s" % self.val['x'] 224 225 def children (self): 226 yield 's', self.val['s'] 227 yield 'x', self.val['x'] 228 229class MemoryErrorString (object): 230 "Raise an error" 231 232 def __init__(self, val): 233 self.val = val 234 235 def to_string(self): 236 raise gdb.MemoryError ("Cannot access memory.") 237 238 def display_hint (self): 239 return 'string' 240 241class pp_eval_type (object): 242 def __init__(self, val): 243 self.val = val 244 245 def to_string(self): 246 gdb.execute("bt", to_string=True) 247 return "eval=<" + str(gdb.parse_and_eval("eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")) + ">" 248 249class pp_int_typedef (object): 250 def __init__(self, val): 251 self.val = val 252 253 def to_string(self): 254 return "type=%s, val=%s" % (self.val.type, int(self.val)) 255 256class pp_int_typedef3 (object): 257 "A printer without a to_string method" 258 259 def __init__(self, val): 260 self.val = val 261 262 def children(self): 263 yield 's', 27 264 265def lookup_function (val): 266 "Look-up and return a pretty-printer that can print val." 267 268 # Get the type. 269 type = val.type 270 271 # If it points to a reference, get the reference. 272 if type.code == gdb.TYPE_CODE_REF: 273 type = type.target () 274 275 # Get the unqualified type, stripped of typedefs. 276 type = type.unqualified ().strip_typedefs () 277 278 # Get the type name. 279 typename = type.tag 280 281 if typename == None: 282 return None 283 284 # Iterate over local dictionary of types to determine 285 # if a printer is registered for that type. Return an 286 # instantiation of the printer if found. 287 for function in pretty_printers_dict: 288 if function.match (typename): 289 return pretty_printers_dict[function] (val) 290 291 # Cannot find a pretty printer. Return None. 292 293 return None 294 295def disable_lookup_function (): 296 lookup_function.enabled = False 297 298def enable_lookup_function (): 299 lookup_function.enabled = True 300 301# Lookup a printer for VAL in the typedefs dict. 302def lookup_typedefs_function (val): 303 "Look-up and return a pretty-printer that can print val (typedefs)." 304 305 # Get the type. 306 type = val.type 307 308 if type == None or type.name == None or type.code != gdb.TYPE_CODE_TYPEDEF: 309 return None 310 311 # Iterate over local dictionary of typedef types to determine if a 312 # printer is registered for that type. Return an instantiation of 313 # the printer if found. 314 for function in typedefs_pretty_printers_dict: 315 if function.match (type.name): 316 return typedefs_pretty_printers_dict[function] (val) 317 318 # Cannot find a pretty printer. 319 return None 320 321def register_pretty_printers (): 322 pretty_printers_dict[re.compile ('^struct s$')] = pp_s 323 pretty_printers_dict[re.compile ('^s$')] = pp_s 324 pretty_printers_dict[re.compile ('^S$')] = pp_s 325 326 pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss 327 pretty_printers_dict[re.compile ('^ss$')] = pp_ss 328 pretty_printers_dict[re.compile ('^const S &$')] = pp_s 329 pretty_printers_dict[re.compile ('^SSS$')] = pp_sss 330 331 pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual 332 pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 333 334 pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr 335 pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr 336 337 # Note that we purposely omit the typedef names here. 338 # Printer lookup is based on canonical name. 339 # However, we do need both tagged and untagged variants, to handle 340 # both the C and C++ cases. 341 pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print 342 pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter 343 pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter 344 pretty_printers_dict[re.compile ('^string_repr$')] = string_print 345 pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter 346 pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter 347 348 pretty_printers_dict[re.compile ('^struct to_string_returns_value_inner$')] = ToStringReturnsValueInner 349 pretty_printers_dict[re.compile ('^to_string_returns_value_inner$')] = ToStringReturnsValueInner 350 pretty_printers_dict[re.compile ('^struct to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper 351 pretty_printers_dict[re.compile ('^to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper 352 353 pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns 354 pretty_printers_dict[re.compile ('^ns$')] = pp_ns 355 356 pretty_printers_dict[re.compile ('^struct lazystring$')] = pp_ls 357 pretty_printers_dict[re.compile ('^lazystring$')] = pp_ls 358 359 pretty_printers_dict[re.compile ('^struct outerstruct$')] = pp_outer 360 pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer 361 362 pretty_printers_dict[re.compile ('^struct hint_error$')] = pp_hint_error 363 pretty_printers_dict[re.compile ('^hint_error$')] = pp_hint_error 364 365 pretty_printers_dict[re.compile ('^struct children_as_list$')] = pp_children_as_list 366 pretty_printers_dict[re.compile ('^children_as_list$')] = pp_children_as_list 367 368 pretty_printers_dict[re.compile ('^memory_error$')] = MemoryErrorString 369 370 pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type 371 372 typedefs_pretty_printers_dict[re.compile ('^int_type$')] = pp_int_typedef 373 typedefs_pretty_printers_dict[re.compile ('^int_type2$')] = pp_int_typedef 374 typedefs_pretty_printers_dict[re.compile ('^int_type3$')] = pp_int_typedef3 375 376# Dict for struct types with typedefs fully stripped. 377pretty_printers_dict = {} 378# Dict for typedef types. 379typedefs_pretty_printers_dict = {} 380 381register_pretty_printers () 382gdb.pretty_printers.append (lookup_function) 383gdb.pretty_printers.append (lookup_typedefs_function) 384