1 import gdb.printing 2 3 class Iterator: 4 def __iter__(self): 5 return self 6 7 # Python 2 compatibility 8 def next(self): 9 return self.__next__() 10 11 def children(self): 12 return self 13 14 def escape_bytes(val, l): 15 return '"' + val.string(encoding='Latin-1', length=l).encode('unicode_escape').decode() + '"' 16 17 class SmallStringPrinter: 18 """Print an llvm::SmallString object.""" 19 20 def __init__(self, val): 21 self.val = val 22 23 def to_string(self): 24 begin = self.val['BeginX'] 25 return escape_bytes(begin.cast(gdb.lookup_type('char').pointer()), self.val['Size']) 26 27 class StringRefPrinter: 28 """Print an llvm::StringRef object.""" 29 30 def __init__(self, val): 31 self.val = val 32 33 def to_string(self): 34 return escape_bytes(self.val['Data'], self.val['Length']) 35 36 class SmallVectorPrinter(Iterator): 37 """Print an llvm::SmallVector object.""" 38 39 def __init__(self, val): 40 self.val = val 41 t = val.type.template_argument(0).pointer() 42 self.begin = val['BeginX'].cast(t) 43 self.size = val['Size'] 44 self.i = 0 45 46 def __next__(self): 47 if self.i == self.size: 48 raise StopIteration 49 ret = '[{}]'.format(self.i), (self.begin+self.i).dereference() 50 self.i += 1 51 return ret 52 53 def to_string(self): 54 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity']) 55 56 def display_hint (self): 57 return 'array' 58 59 class ArrayRefPrinter: 60 """Print an llvm::ArrayRef object.""" 61 62 class _iterator: 63 def __init__(self, begin, end): 64 self.cur = begin 65 self.end = end 66 self.count = 0 67 68 def __iter__(self): 69 return self 70 71 def next(self): 72 if self.cur == self.end: 73 raise StopIteration 74 count = self.count 75 self.count = self.count + 1 76 cur = self.cur 77 self.cur = self.cur + 1 78 return '[%d]' % count, cur.dereference() 79 80 __next__ = next 81 82 def __init__(self, val): 83 self.val = val 84 85 __next__ = next 86 87 def children(self): 88 data = self.val['Data'] 89 return self._iterator(data, data + self.val['Length']) 90 91 def to_string(self): 92 return 'llvm::ArrayRef of length %d' % (self.val['Length']) 93 94 def display_hint (self): 95 return 'array' 96 97 class ExpectedPrinter(Iterator): 98 """Print an llvm::Expected object.""" 99 100 def __init__(self, val): 101 self.val = val 102 103 def __next__(self): 104 val = self.val 105 if val is None: 106 raise StopIteration 107 self.val = None 108 if val['HasError']: 109 return ('error', val['ErrorStorage'].address.cast( 110 gdb.lookup_type('llvm::ErrorInfoBase').pointer()).dereference()) 111 return ('value', val['TStorage'].address.cast( 112 val.type.template_argument(0).pointer()).dereference()) 113 114 def to_string(self): 115 return 'llvm::Expected{}'.format(' is error' if self.val['HasError'] else '') 116 117 class OptionalPrinter(Iterator): 118 """Print an llvm::Optional object.""" 119 120 def __init__(self, val): 121 self.val = val 122 123 def __next__(self): 124 val = self.val 125 if val is None: 126 raise StopIteration 127 self.val = None 128 if not val['Storage']['hasVal']: 129 raise StopIteration 130 return ('value', val['Storage']['storage']['buffer'].address.cast( 131 val.type.template_argument(0).pointer()).dereference()) 132 133 def to_string(self): 134 return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized') 135 136 class DenseMapPrinter: 137 "Print a DenseMap" 138 139 class _iterator: 140 def __init__(self, key_info_t, begin, end): 141 self.key_info_t = key_info_t 142 self.cur = begin 143 self.end = end 144 self.advancePastEmptyBuckets() 145 self.first = True 146 147 def __iter__(self): 148 return self 149 150 def advancePastEmptyBuckets(self): 151 # disabled until the comments below can be addressed 152 # keeping as notes/posterity/hints for future contributors 153 return 154 n = self.key_info_t.name 155 is_equal = gdb.parse_and_eval(n + '::isEqual') 156 empty = gdb.parse_and_eval(n + '::getEmptyKey()') 157 tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()') 158 # the following is invalid, GDB fails with: 159 # Python Exception <class 'gdb.error'> Attempt to take address of value 160 # not located in memory. 161 # because isEqual took parameter (for the unsigned long key I was testing) 162 # by const ref, and GDB 163 # It's also not entirely general - we should be accessing the "getFirst()" 164 # member function, not the 'first' member variable, but I've yet to figure 165 # out how to find/call member functions (especially (const) overloaded 166 # ones) on a gdb.Value. 167 while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)): 168 self.cur = self.cur + 1 169 170 def next(self): 171 if self.cur == self.end: 172 raise StopIteration 173 cur = self.cur 174 v = cur.dereference()['first' if self.first else 'second'] 175 if not self.first: 176 self.cur = self.cur + 1 177 self.advancePastEmptyBuckets() 178 self.first = True 179 else: 180 self.first = False 181 return 'x', v 182 183 __next__ = next 184 185 def __init__(self, val): 186 self.val = val 187 188 def children(self): 189 t = self.val.type.template_argument(3).pointer() 190 begin = self.val['Buckets'].cast(t) 191 end = (begin + self.val['NumBuckets']).cast(t) 192 return self._iterator(self.val.type.template_argument(2), begin, end) 193 194 def to_string(self): 195 return 'llvm::DenseMap with %d elements' % (self.val['NumEntries']) 196 197 def display_hint(self): 198 return 'map' 199 200 class TwinePrinter: 201 "Print a Twine" 202 203 def __init__(self, val): 204 self._val = val 205 206 def display_hint(self): 207 return 'string' 208 209 def string_from_pretty_printer_lookup(self, val): 210 '''Lookup the default pretty-printer for val and use it. 211 212 If no pretty-printer is defined for the type of val, print an error and 213 return a placeholder string.''' 214 215 pp = gdb.default_visualizer(val) 216 if pp: 217 s = pp.to_string() 218 219 # The pretty-printer may return a LazyString instead of an actual Python 220 # string. Convert it to a Python string. However, GDB doesn't seem to 221 # register the LazyString type, so we can't check 222 # "type(s) == gdb.LazyString". 223 if 'LazyString' in type(s).__name__: 224 s = s.value().address.string() 225 226 else: 227 print(('No pretty printer for {} found. The resulting Twine ' + 228 'representation will be incomplete.').format(val.type.name)) 229 s = '(missing {})'.format(val.type.name) 230 231 return s 232 233 def is_twine_kind(self, kind, expected): 234 if not kind.endswith(expected): 235 return False 236 # apparently some GDB versions add the NodeKind:: namespace 237 # (happens for me on GDB 7.11) 238 return kind in ('llvm::Twine::' + expected, 239 'llvm::Twine::NodeKind::' + expected) 240 241 def string_from_child(self, child, kind): 242 '''Return the string representation of the Twine::Child child.''' 243 244 if self.is_twine_kind(kind, 'EmptyKind') or self.is_twine_kind(kind, 'NullKind'): 245 return '' 246 247 if self.is_twine_kind(kind, 'TwineKind'): 248 return self.string_from_twine_object(child['twine'].dereference()) 249 250 if self.is_twine_kind(kind, 'CStringKind'): 251 return child['cString'].string() 252 253 if self.is_twine_kind(kind, 'StdStringKind'): 254 val = child['stdString'].dereference() 255 return self.string_from_pretty_printer_lookup(val) 256 257 if self.is_twine_kind(kind, 'StringRefKind'): 258 val = child['stringRef'].dereference() 259 pp = StringRefPrinter(val) 260 return pp.to_string() 261 262 if self.is_twine_kind(kind, 'SmallStringKind'): 263 val = child['smallString'].dereference() 264 pp = SmallStringPrinter(val) 265 return pp.to_string() 266 267 if self.is_twine_kind(kind, 'CharKind'): 268 return chr(child['character']) 269 270 if self.is_twine_kind(kind, 'DecUIKind'): 271 return str(child['decUI']) 272 273 if self.is_twine_kind(kind, 'DecIKind'): 274 return str(child['decI']) 275 276 if self.is_twine_kind(kind, 'DecULKind'): 277 return str(child['decUL'].dereference()) 278 279 if self.is_twine_kind(kind, 'DecLKind'): 280 return str(child['decL'].dereference()) 281 282 if self.is_twine_kind(kind, 'DecULLKind'): 283 return str(child['decULL'].dereference()) 284 285 if self.is_twine_kind(kind, 'DecLLKind'): 286 return str(child['decLL'].dereference()) 287 288 if self.is_twine_kind(kind, 'UHexKind'): 289 val = child['uHex'].dereference() 290 return hex(int(val)) 291 292 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be ' 293 'incomplete.').format(kind)) 294 295 return '(unhandled {})'.format(kind) 296 297 def string_from_twine_object(self, twine): 298 '''Return the string representation of the Twine object twine.''' 299 300 lhs_str = '' 301 rhs_str = '' 302 303 lhs = twine['LHS'] 304 rhs = twine['RHS'] 305 lhs_kind = str(twine['LHSKind']) 306 rhs_kind = str(twine['RHSKind']) 307 308 lhs_str = self.string_from_child(lhs, lhs_kind) 309 rhs_str = self.string_from_child(rhs, rhs_kind) 310 311 return lhs_str + rhs_str 312 313 def to_string(self): 314 return self.string_from_twine_object(self._val) 315 316 pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport") 317 pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter) 318 pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter) 319 pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter) 320 pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter) 321 pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter) 322 pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter) 323 pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter) 324 pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter) 325 gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) 326