1from __future__ import print_function 2import sys 3 4import gdb.printing 5import gdb.types 6 7class Iterator: 8 def __iter__(self): 9 return self 10 11 if sys.version_info.major == 2: 12 def next(self): 13 return self.__next__() 14 15 def children(self): 16 return self 17 18def escape_bytes(val, l): 19 return '"' + val.string(encoding='Latin-1', length=l).encode('unicode_escape').decode() + '"' 20 21class SmallStringPrinter: 22 """Print an llvm::SmallString object.""" 23 24 def __init__(self, val): 25 self.val = val 26 27 def to_string(self): 28 begin = self.val['BeginX'] 29 return escape_bytes(begin.cast(gdb.lookup_type('char').pointer()), self.val['Size']) 30 31class StringRefPrinter: 32 """Print an llvm::StringRef object.""" 33 34 def __init__(self, val): 35 self.val = val 36 37 def to_string(self): 38 return escape_bytes(self.val['Data'], self.val['Length']) 39 40class SmallVectorPrinter(Iterator): 41 """Print an llvm::SmallVector object.""" 42 43 def __init__(self, val): 44 self.val = val 45 t = val.type.template_argument(0).pointer() 46 self.begin = val['BeginX'].cast(t) 47 self.size = val['Size'] 48 self.i = 0 49 50 def __next__(self): 51 if self.i == self.size: 52 raise StopIteration 53 ret = '[{}]'.format(self.i), (self.begin+self.i).dereference() 54 self.i += 1 55 return ret 56 57 def to_string(self): 58 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity']) 59 60 def display_hint (self): 61 return 'array' 62 63class ArrayRefPrinter: 64 """Print an llvm::ArrayRef object.""" 65 66 class _iterator: 67 def __init__(self, begin, end): 68 self.cur = begin 69 self.end = end 70 self.count = 0 71 72 def __iter__(self): 73 return self 74 75 def __next__(self): 76 if self.cur == self.end: 77 raise StopIteration 78 count = self.count 79 self.count = self.count + 1 80 cur = self.cur 81 self.cur = self.cur + 1 82 return '[%d]' % count, cur.dereference() 83 84 if sys.version_info.major == 2: 85 next = __next__ 86 87 def __init__(self, val): 88 self.val = val 89 90 def children(self): 91 data = self.val['Data'] 92 return self._iterator(data, data + self.val['Length']) 93 94 def to_string(self): 95 return 'llvm::ArrayRef of length %d' % (self.val['Length']) 96 97 def display_hint (self): 98 return 'array' 99 100class ExpectedPrinter(Iterator): 101 """Print an llvm::Expected object.""" 102 103 def __init__(self, val): 104 self.val = val 105 106 def __next__(self): 107 val = self.val 108 if val is None: 109 raise StopIteration 110 self.val = None 111 if val['HasError']: 112 return ('error', val['ErrorStorage'].address.cast( 113 gdb.lookup_type('llvm::ErrorInfoBase').pointer()).dereference()) 114 return ('value', val['TStorage'].address.cast( 115 val.type.template_argument(0).pointer()).dereference()) 116 117 def to_string(self): 118 return 'llvm::Expected{}'.format(' is error' if self.val['HasError'] else '') 119 120class OptionalPrinter(Iterator): 121 """Print an llvm::Optional object.""" 122 123 def __init__(self, val): 124 self.val = val 125 126 def __next__(self): 127 val = self.val 128 if val is None: 129 raise StopIteration 130 self.val = None 131 if not val['Storage']['hasVal']: 132 raise StopIteration 133 return ('value', val['Storage']['value']) 134 135 def to_string(self): 136 return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized') 137 138class DenseMapPrinter: 139 "Print a DenseMap" 140 141 class _iterator: 142 def __init__(self, key_info_t, begin, end): 143 self.key_info_t = key_info_t 144 self.cur = begin 145 self.end = end 146 self.advancePastEmptyBuckets() 147 self.first = True 148 149 def __iter__(self): 150 return self 151 152 def advancePastEmptyBuckets(self): 153 # disabled until the comments below can be addressed 154 # keeping as notes/posterity/hints for future contributors 155 return 156 n = self.key_info_t.name 157 is_equal = gdb.parse_and_eval(n + '::isEqual') 158 empty = gdb.parse_and_eval(n + '::getEmptyKey()') 159 tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()') 160 # the following is invalid, GDB fails with: 161 # Python Exception <class 'gdb.error'> Attempt to take address of value 162 # not located in memory. 163 # because isEqual took parameter (for the unsigned long key I was testing) 164 # by const ref, and GDB 165 # It's also not entirely general - we should be accessing the "getFirst()" 166 # member function, not the 'first' member variable, but I've yet to figure 167 # out how to find/call member functions (especially (const) overloaded 168 # ones) on a gdb.Value. 169 while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)): 170 self.cur = self.cur + 1 171 172 def __next__(self): 173 if self.cur == self.end: 174 raise StopIteration 175 cur = self.cur 176 v = cur.dereference()['first' if self.first else 'second'] 177 if not self.first: 178 self.cur = self.cur + 1 179 self.advancePastEmptyBuckets() 180 self.first = True 181 else: 182 self.first = False 183 return 'x', v 184 185 if sys.version_info.major == 2: 186 next = __next__ 187 188 def __init__(self, val): 189 self.val = val 190 191 def children(self): 192 t = self.val.type.template_argument(3).pointer() 193 begin = self.val['Buckets'].cast(t) 194 end = (begin + self.val['NumBuckets']).cast(t) 195 return self._iterator(self.val.type.template_argument(2), begin, end) 196 197 def to_string(self): 198 return 'llvm::DenseMap with %d elements' % (self.val['NumEntries']) 199 200 def display_hint(self): 201 return 'map' 202 203class TwinePrinter: 204 "Print a Twine" 205 206 def __init__(self, val): 207 self._val = val 208 209 def display_hint(self): 210 return 'string' 211 212 def string_from_pretty_printer_lookup(self, val): 213 '''Lookup the default pretty-printer for val and use it. 214 215 If no pretty-printer is defined for the type of val, print an error and 216 return a placeholder string.''' 217 218 pp = gdb.default_visualizer(val) 219 if pp: 220 s = pp.to_string() 221 222 # The pretty-printer may return a LazyString instead of an actual Python 223 # string. Convert it to a Python string. However, GDB doesn't seem to 224 # register the LazyString type, so we can't check 225 # "type(s) == gdb.LazyString". 226 if 'LazyString' in type(s).__name__: 227 s = s.value().address.string() 228 229 else: 230 print(('No pretty printer for {} found. The resulting Twine ' + 231 'representation will be incomplete.').format(val.type.name)) 232 s = '(missing {})'.format(val.type.name) 233 234 return s 235 236 def is_twine_kind(self, kind, expected): 237 if not kind.endswith(expected): 238 return False 239 # apparently some GDB versions add the NodeKind:: namespace 240 # (happens for me on GDB 7.11) 241 return kind in ('llvm::Twine::' + expected, 242 'llvm::Twine::NodeKind::' + expected) 243 244 def string_from_child(self, child, kind): 245 '''Return the string representation of the Twine::Child child.''' 246 247 if self.is_twine_kind(kind, 'EmptyKind') or self.is_twine_kind(kind, 'NullKind'): 248 return '' 249 250 if self.is_twine_kind(kind, 'TwineKind'): 251 return self.string_from_twine_object(child['twine'].dereference()) 252 253 if self.is_twine_kind(kind, 'CStringKind'): 254 return child['cString'].string() 255 256 if self.is_twine_kind(kind, 'StdStringKind'): 257 val = child['stdString'].dereference() 258 return self.string_from_pretty_printer_lookup(val) 259 260 if self.is_twine_kind(kind, 'StringRefKind'): 261 val = child['stringRef'].dereference() 262 pp = StringRefPrinter(val) 263 return pp.to_string() 264 265 if self.is_twine_kind(kind, 'SmallStringKind'): 266 val = child['smallString'].dereference() 267 pp = SmallStringPrinter(val) 268 return pp.to_string() 269 270 if self.is_twine_kind(kind, 'CharKind'): 271 return chr(child['character']) 272 273 if self.is_twine_kind(kind, 'DecUIKind'): 274 return str(child['decUI']) 275 276 if self.is_twine_kind(kind, 'DecIKind'): 277 return str(child['decI']) 278 279 if self.is_twine_kind(kind, 'DecULKind'): 280 return str(child['decUL'].dereference()) 281 282 if self.is_twine_kind(kind, 'DecLKind'): 283 return str(child['decL'].dereference()) 284 285 if self.is_twine_kind(kind, 'DecULLKind'): 286 return str(child['decULL'].dereference()) 287 288 if self.is_twine_kind(kind, 'DecLLKind'): 289 return str(child['decLL'].dereference()) 290 291 if self.is_twine_kind(kind, 'UHexKind'): 292 val = child['uHex'].dereference() 293 return hex(int(val)) 294 295 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be ' 296 'incomplete.').format(kind)) 297 298 return '(unhandled {})'.format(kind) 299 300 def string_from_twine_object(self, twine): 301 '''Return the string representation of the Twine object twine.''' 302 303 lhs_str = '' 304 rhs_str = '' 305 306 lhs = twine['LHS'] 307 rhs = twine['RHS'] 308 lhs_kind = str(twine['LHSKind']) 309 rhs_kind = str(twine['RHSKind']) 310 311 lhs_str = self.string_from_child(lhs, lhs_kind) 312 rhs_str = self.string_from_child(rhs, rhs_kind) 313 314 return lhs_str + rhs_str 315 316 def to_string(self): 317 return self.string_from_twine_object(self._val) 318 319def get_pointer_int_pair(val): 320 """Get tuple from llvm::PointerIntPair.""" 321 info_name = val.type.template_argument(4).strip_typedefs().name 322 # Note: this throws a gdb.error if the info type is not used (by means of a 323 # call to getPointer() or similar) in the current translation unit. 324 enum_type = gdb.lookup_type(info_name + '::MaskAndShiftConstants') 325 enum_dict = gdb.types.make_enum_dict(enum_type) 326 ptr_mask = enum_dict[info_name + '::PointerBitMask'] 327 int_shift = enum_dict[info_name + '::IntShift'] 328 int_mask = enum_dict[info_name + '::IntMask'] 329 pair_union = val['Value'] 330 pointer = (pair_union & ptr_mask) 331 value = ((pair_union >> int_shift) & int_mask) 332 return (pointer, value) 333 334class PointerIntPairPrinter: 335 """Print a PointerIntPair.""" 336 337 def __init__(self, pointer, value): 338 self.pointer = pointer 339 self.value = value 340 341 def children(self): 342 yield ('pointer', self.pointer) 343 yield ('value', self.value) 344 345def make_pointer_int_pair_printer(val): 346 """Factory for an llvm::PointerIntPair printer.""" 347 try: 348 pointer, value = get_pointer_int_pair(val) 349 except gdb.error: 350 return None # If PointerIntPair cannot be analyzed, print as raw value. 351 pointer_type = val.type.template_argument(0) 352 value_type = val.type.template_argument(2) 353 return PointerIntPairPrinter(pointer.cast(pointer_type), 354 value.cast(value_type)) 355 356class PointerUnionPrinter: 357 """Print a PointerUnion.""" 358 359 def __init__(self, pointer): 360 self.pointer = pointer 361 362 def children(self): 363 yield ('pointer', self.pointer) 364 365 def to_string(self): 366 return "Containing %s" % self.pointer.type 367 368def make_pointer_union_printer(val): 369 """Factory for an llvm::PointerUnion printer.""" 370 try: 371 pointer, value = get_pointer_int_pair(val['Val']) 372 except gdb.error: 373 return None # If PointerIntPair cannot be analyzed, print as raw value. 374 pointer_type = val.type.template_argument(int(value)) 375 return PointerUnionPrinter(pointer.cast(pointer_type)) 376 377class IlistNodePrinter: 378 """Print an llvm::ilist_node object.""" 379 380 def __init__(self, val): 381 impl_type = val.type.fields()[0].type 382 base_type = impl_type.fields()[0].type 383 derived_type = val.type.template_argument(0) 384 385 def get_prev_and_sentinel(base): 386 # One of Prev and PrevAndSentinel exists. Depending on #defines used to 387 # compile LLVM, the base_type's template argument is either true of false. 388 if base_type.template_argument(0): 389 return get_pointer_int_pair(base['PrevAndSentinel']) 390 return base['Prev'], None 391 392 # Casts a base_type pointer to the appropriate derived type. 393 def cast_pointer(pointer): 394 sentinel = get_prev_and_sentinel(pointer.dereference())[1] 395 pointer = pointer.cast(impl_type.pointer()) 396 if sentinel: 397 return pointer 398 return pointer.cast(derived_type.pointer()) 399 400 # Repeated cast becaue val.type's base_type is ambiguous when using tags. 401 base = val.cast(impl_type).cast(base_type) 402 (prev, sentinel) = get_prev_and_sentinel(base) 403 prev = prev.cast(base_type.pointer()) 404 self.prev = cast_pointer(prev) 405 self.next = cast_pointer(val['Next']) 406 self.sentinel = sentinel 407 408 def children(self): 409 if self.sentinel: 410 yield 'sentinel', 'yes' 411 yield 'prev', self.prev 412 yield 'next', self.next 413 414class IlistPrinter: 415 """Print an llvm::simple_ilist or llvm::iplist object.""" 416 417 def __init__(self, val): 418 self.node_type = val.type.template_argument(0) 419 sentinel = val['Sentinel'] 420 # First field is common base type of sentinel and ilist_node. 421 base_type = sentinel.type.fields()[0].type 422 self.sentinel = sentinel.address.cast(base_type.pointer()) 423 424 def _pointers(self): 425 pointer = self.sentinel 426 while True: 427 pointer = pointer['Next'].cast(pointer.type) 428 if pointer == self.sentinel: 429 return 430 yield pointer.cast(self.node_type.pointer()) 431 432 def children(self): 433 for k, v in enumerate(self._pointers()): 434 yield ('[%d]' % k, v.dereference()) 435 436 437pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport") 438pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter) 439pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter) 440pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter) 441pp.add_printer('llvm::ArrayRef', '^llvm::(Mutable)?ArrayRef<.*>$', ArrayRefPrinter) 442pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter) 443pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter) 444pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter) 445pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter) 446pp.add_printer('llvm::PointerIntPair', '^llvm::PointerIntPair<.*>$', make_pointer_int_pair_printer) 447pp.add_printer('llvm::PointerUnion', '^llvm::PointerUnion<.*>$', make_pointer_union_printer) 448pp.add_printer('llvm::ilist_node', '^llvm::ilist_node<.*>$', IlistNodePrinter) 449pp.add_printer('llvm::iplist', '^llvm::iplist<.*>$', IlistPrinter) 450pp.add_printer('llvm::simple_ilist', '^llvm::simple_ilist<.*>$', IlistPrinter) 451gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) 452