1# Copyright (C) 2008-2017 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 87class pp_s (object): 88 def __init__(self, val): 89 self.val = val 90 91 def to_string(self): 92 a = self.val["a"] 93 b = self.val["b"] 94 if a.address != b: 95 raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b))) 96 return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 97 98class pp_ss (object): 99 def __init__(self, val): 100 self.val = val 101 102 def to_string(self): 103 return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 104 105class pp_sss (object): 106 def __init__(self, val): 107 self.val = val 108 109 def to_string(self): 110 return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">" 111 112class pp_multiple_virtual (object): 113 def __init__ (self, val): 114 self.val = val 115 116 def to_string (self): 117 return "pp value variable is: " + str (self.val['value']) 118 119class pp_vbase1 (object): 120 def __init__ (self, val): 121 self.val = val 122 123 def to_string (self): 124 return "pp class name: " + self.val.type.tag 125 126class pp_nullstr (object): 127 def __init__(self, val): 128 self.val = val 129 130 def to_string(self): 131 return self.val['s'].string(gdb.target_charset()) 132 133class pp_ns (object): 134 "Print a std::basic_string of some kind" 135 136 def __init__(self, val): 137 self.val = val 138 139 def to_string(self): 140 len = self.val['length'] 141 return self.val['null_str'].string (gdb.target_charset(), length = len) 142 143 def display_hint (self): 144 return 'string' 145 146pp_ls_encoding = None 147 148class pp_ls (object): 149 "Print a std::basic_string of some kind" 150 151 def __init__(self, val): 152 self.val = val 153 154 def to_string(self): 155 length = self.val['len'] 156 if pp_ls_encoding is not None: 157 if length >= 0: 158 return self.val['lazy_str'].lazy_string( 159 encoding = pp_ls_encoding, 160 length = length) 161 else: 162 return self.val['lazy_str'].lazy_string( 163 encoding = pp_ls_encoding) 164 else: 165 if length >= 0: 166 return self.val['lazy_str'].lazy_string(length = length) 167 else: 168 return self.val['lazy_str'].lazy_string() 169 170 def display_hint (self): 171 return 'string' 172 173class pp_hint_error (object): 174 "Throw error from display_hint" 175 176 def __init__(self, val): 177 self.val = val 178 179 def to_string(self): 180 return 'hint_error_val' 181 182 def display_hint (self): 183 raise Exception("hint failed") 184 185class pp_children_as_list (object): 186 "Throw error from display_hint" 187 188 def __init__(self, val): 189 self.val = val 190 191 def to_string(self): 192 return 'children_as_list_val' 193 194 def children (self): 195 return [('one', 1)] 196 197class pp_outer (object): 198 "Print struct outer" 199 200 def __init__ (self, val): 201 self.val = val 202 203 def to_string (self): 204 return "x = %s" % self.val['x'] 205 206 def children (self): 207 yield 's', self.val['s'] 208 yield 'x', self.val['x'] 209 210class MemoryErrorString (object): 211 "Raise an error" 212 213 def __init__(self, val): 214 self.val = val 215 216 def to_string(self): 217 raise gdb.MemoryError ("Cannot access memory.") 218 219 def display_hint (self): 220 return 'string' 221 222class pp_eval_type (object): 223 def __init__(self, val): 224 self.val = val 225 226 def to_string(self): 227 gdb.execute("bt", to_string=True) 228 return "eval=<" + str(gdb.parse_and_eval("eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")) + ">" 229 230def lookup_function (val): 231 "Look-up and return a pretty-printer that can print val." 232 233 # Get the type. 234 type = val.type 235 236 # If it points to a reference, get the reference. 237 if type.code == gdb.TYPE_CODE_REF: 238 type = type.target () 239 240 # Get the unqualified type, stripped of typedefs. 241 type = type.unqualified ().strip_typedefs () 242 243 # Get the type name. 244 typename = type.tag 245 246 if typename == None: 247 return None 248 249 # Iterate over local dictionary of types to determine 250 # if a printer is registered for that type. Return an 251 # instantiation of the printer if found. 252 for function in pretty_printers_dict: 253 if function.match (typename): 254 return pretty_printers_dict[function] (val) 255 256 # Cannot find a pretty printer. Return None. 257 258 return None 259 260def disable_lookup_function (): 261 lookup_function.enabled = False 262 263def enable_lookup_function (): 264 lookup_function.enabled = True 265 266def register_pretty_printers (): 267 pretty_printers_dict[re.compile ('^struct s$')] = pp_s 268 pretty_printers_dict[re.compile ('^s$')] = pp_s 269 pretty_printers_dict[re.compile ('^S$')] = pp_s 270 271 pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss 272 pretty_printers_dict[re.compile ('^ss$')] = pp_ss 273 pretty_printers_dict[re.compile ('^const S &$')] = pp_s 274 pretty_printers_dict[re.compile ('^SSS$')] = pp_sss 275 276 pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual 277 pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 278 279 pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr 280 pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr 281 282 # Note that we purposely omit the typedef names here. 283 # Printer lookup is based on canonical name. 284 # However, we do need both tagged and untagged variants, to handle 285 # both the C and C++ cases. 286 pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print 287 pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter 288 pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter 289 pretty_printers_dict[re.compile ('^string_repr$')] = string_print 290 pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter 291 pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter 292 293 pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns 294 pretty_printers_dict[re.compile ('^ns$')] = pp_ns 295 296 pretty_printers_dict[re.compile ('^struct lazystring$')] = pp_ls 297 pretty_printers_dict[re.compile ('^lazystring$')] = pp_ls 298 299 pretty_printers_dict[re.compile ('^struct outerstruct$')] = pp_outer 300 pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer 301 302 pretty_printers_dict[re.compile ('^struct hint_error$')] = pp_hint_error 303 pretty_printers_dict[re.compile ('^hint_error$')] = pp_hint_error 304 305 pretty_printers_dict[re.compile ('^struct children_as_list$')] = pp_children_as_list 306 pretty_printers_dict[re.compile ('^children_as_list$')] = pp_children_as_list 307 308 pretty_printers_dict[re.compile ('^memory_error$')] = MemoryErrorString 309 310 pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type 311 312pretty_printers_dict = {} 313 314register_pretty_printers () 315gdb.pretty_printers.append (lookup_function) 316