1from __future__ import print_function 2 3import gdb.printing 4 5class Iterator: 6 def __iter__(self): 7 return self 8 9 # Python 2 compatibility 10 def next(self): 11 return self.__next__() 12 13 def children(self): 14 return self 15 16def escape_bytes(val, l): 17 return '"' + val.string(encoding='Latin-1', length=l).encode('unicode_escape').decode() + '"' 18 19class SmallStringPrinter: 20 """Print an llvm::SmallString object.""" 21 22 def __init__(self, val): 23 self.val = val 24 25 def to_string(self): 26 begin = self.val['BeginX'] 27 return escape_bytes(begin.cast(gdb.lookup_type('char').pointer()), self.val['Size']) 28 29class StringRefPrinter: 30 """Print an llvm::StringRef object.""" 31 32 def __init__(self, val): 33 self.val = val 34 35 def to_string(self): 36 return escape_bytes(self.val['Data'], self.val['Length']) 37 38class SmallVectorPrinter(Iterator): 39 """Print an llvm::SmallVector object.""" 40 41 def __init__(self, val): 42 self.val = val 43 t = val.type.template_argument(0).pointer() 44 self.begin = val['BeginX'].cast(t) 45 self.size = val['Size'] 46 self.i = 0 47 48 def __next__(self): 49 if self.i == self.size: 50 raise StopIteration 51 ret = '[{}]'.format(self.i), (self.begin+self.i).dereference() 52 self.i += 1 53 return ret 54 55 def to_string(self): 56 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity']) 57 58 def display_hint (self): 59 return 'array' 60 61class ArrayRefPrinter: 62 """Print an llvm::ArrayRef object.""" 63 64 class _iterator: 65 def __init__(self, begin, end): 66 self.cur = begin 67 self.end = end 68 self.count = 0 69 70 def __iter__(self): 71 return self 72 73 def next(self): 74 if self.cur == self.end: 75 raise StopIteration 76 count = self.count 77 self.count = self.count + 1 78 cur = self.cur 79 self.cur = self.cur + 1 80 return '[%d]' % count, cur.dereference() 81 82 __next__ = next 83 84 def __init__(self, val): 85 self.val = val 86 87 __next__ = next 88 89 def children(self): 90 data = self.val['Data'] 91 return self._iterator(data, data + self.val['Length']) 92 93 def to_string(self): 94 return 'llvm::ArrayRef of length %d' % (self.val['Length']) 95 96 def display_hint (self): 97 return 'array' 98 99class ExpectedPrinter(Iterator): 100 """Print an llvm::Expected object.""" 101 102 def __init__(self, val): 103 self.val = val 104 105 def __next__(self): 106 val = self.val 107 if val is None: 108 raise StopIteration 109 self.val = None 110 if val['HasError']: 111 return ('error', val['ErrorStorage'].address.cast( 112 gdb.lookup_type('llvm::ErrorInfoBase').pointer()).dereference()) 113 return ('value', val['TStorage'].address.cast( 114 val.type.template_argument(0).pointer()).dereference()) 115 116 def to_string(self): 117 return 'llvm::Expected{}'.format(' is error' if self.val['HasError'] else '') 118 119class OptionalPrinter(Iterator): 120 """Print an llvm::Optional object.""" 121 122 def __init__(self, val): 123 self.val = val 124 125 def __next__(self): 126 val = self.val 127 if val is None: 128 raise StopIteration 129 self.val = None 130 if not val['Storage']['hasVal']: 131 raise StopIteration 132 return ('value', val['Storage']['storage']['buffer'].address.cast( 133 val.type.template_argument(0).pointer()).dereference()) 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 __next__ = next 186 187 def __init__(self, val): 188 self.val = val 189 190 def children(self): 191 t = self.val.type.template_argument(3).pointer() 192 begin = self.val['Buckets'].cast(t) 193 end = (begin + self.val['NumBuckets']).cast(t) 194 return self._iterator(self.val.type.template_argument(2), begin, end) 195 196 def to_string(self): 197 return 'llvm::DenseMap with %d elements' % (self.val['NumEntries']) 198 199 def display_hint(self): 200 return 'map' 201 202class TwinePrinter: 203 "Print a Twine" 204 205 def __init__(self, val): 206 self._val = val 207 208 def display_hint(self): 209 return 'string' 210 211 def string_from_pretty_printer_lookup(self, val): 212 '''Lookup the default pretty-printer for val and use it. 213 214 If no pretty-printer is defined for the type of val, print an error and 215 return a placeholder string.''' 216 217 pp = gdb.default_visualizer(val) 218 if pp: 219 s = pp.to_string() 220 221 # The pretty-printer may return a LazyString instead of an actual Python 222 # string. Convert it to a Python string. However, GDB doesn't seem to 223 # register the LazyString type, so we can't check 224 # "type(s) == gdb.LazyString". 225 if 'LazyString' in type(s).__name__: 226 s = s.value().address.string() 227 228 else: 229 print(('No pretty printer for {} found. The resulting Twine ' + 230 'representation will be incomplete.').format(val.type.name)) 231 s = '(missing {})'.format(val.type.name) 232 233 return s 234 235 def is_twine_kind(self, kind, expected): 236 if not kind.endswith(expected): 237 return False 238 # apparently some GDB versions add the NodeKind:: namespace 239 # (happens for me on GDB 7.11) 240 return kind in ('llvm::Twine::' + expected, 241 'llvm::Twine::NodeKind::' + expected) 242 243 def string_from_child(self, child, kind): 244 '''Return the string representation of the Twine::Child child.''' 245 246 if self.is_twine_kind(kind, 'EmptyKind') or self.is_twine_kind(kind, 'NullKind'): 247 return '' 248 249 if self.is_twine_kind(kind, 'TwineKind'): 250 return self.string_from_twine_object(child['twine'].dereference()) 251 252 if self.is_twine_kind(kind, 'CStringKind'): 253 return child['cString'].string() 254 255 if self.is_twine_kind(kind, 'StdStringKind'): 256 val = child['stdString'].dereference() 257 return self.string_from_pretty_printer_lookup(val) 258 259 if self.is_twine_kind(kind, 'StringRefKind'): 260 val = child['stringRef'].dereference() 261 pp = StringRefPrinter(val) 262 return pp.to_string() 263 264 if self.is_twine_kind(kind, 'SmallStringKind'): 265 val = child['smallString'].dereference() 266 pp = SmallStringPrinter(val) 267 return pp.to_string() 268 269 if self.is_twine_kind(kind, 'CharKind'): 270 return chr(child['character']) 271 272 if self.is_twine_kind(kind, 'DecUIKind'): 273 return str(child['decUI']) 274 275 if self.is_twine_kind(kind, 'DecIKind'): 276 return str(child['decI']) 277 278 if self.is_twine_kind(kind, 'DecULKind'): 279 return str(child['decUL'].dereference()) 280 281 if self.is_twine_kind(kind, 'DecLKind'): 282 return str(child['decL'].dereference()) 283 284 if self.is_twine_kind(kind, 'DecULLKind'): 285 return str(child['decULL'].dereference()) 286 287 if self.is_twine_kind(kind, 'DecLLKind'): 288 return str(child['decLL'].dereference()) 289 290 if self.is_twine_kind(kind, 'UHexKind'): 291 val = child['uHex'].dereference() 292 return hex(int(val)) 293 294 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be ' 295 'incomplete.').format(kind)) 296 297 return '(unhandled {})'.format(kind) 298 299 def string_from_twine_object(self, twine): 300 '''Return the string representation of the Twine object twine.''' 301 302 lhs_str = '' 303 rhs_str = '' 304 305 lhs = twine['LHS'] 306 rhs = twine['RHS'] 307 lhs_kind = str(twine['LHSKind']) 308 rhs_kind = str(twine['RHSKind']) 309 310 lhs_str = self.string_from_child(lhs, lhs_kind) 311 rhs_str = self.string_from_child(rhs, rhs_kind) 312 313 return lhs_str + rhs_str 314 315 def to_string(self): 316 return self.string_from_twine_object(self._val) 317 318pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport") 319pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter) 320pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter) 321pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter) 322pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter) 323pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter) 324pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter) 325pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter) 326pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter) 327gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) 328