1from __future__ import print_function 2import sys 3 4import gdb.printing 5 6class Iterator: 7 def __iter__(self): 8 return self 9 10 if sys.version_info.major == 2: 11 def next(self): 12 return self.__next__() 13 14 def children(self): 15 return self 16 17def escape_bytes(val, l): 18 return '"' + val.string(encoding='Latin-1', length=l).encode('unicode_escape').decode() + '"' 19 20class SmallStringPrinter: 21 """Print an llvm::SmallString object.""" 22 23 def __init__(self, val): 24 self.val = val 25 26 def to_string(self): 27 begin = self.val['BeginX'] 28 return escape_bytes(begin.cast(gdb.lookup_type('char').pointer()), self.val['Size']) 29 30class StringRefPrinter: 31 """Print an llvm::StringRef object.""" 32 33 def __init__(self, val): 34 self.val = val 35 36 def to_string(self): 37 return escape_bytes(self.val['Data'], self.val['Length']) 38 39class SmallVectorPrinter(Iterator): 40 """Print an llvm::SmallVector object.""" 41 42 def __init__(self, val): 43 self.val = val 44 t = val.type.template_argument(0).pointer() 45 self.begin = val['BeginX'].cast(t) 46 self.size = val['Size'] 47 self.i = 0 48 49 def __next__(self): 50 if self.i == self.size: 51 raise StopIteration 52 ret = '[{}]'.format(self.i), (self.begin+self.i).dereference() 53 self.i += 1 54 return ret 55 56 def to_string(self): 57 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity']) 58 59 def display_hint (self): 60 return 'array' 61 62class ArrayRefPrinter: 63 """Print an llvm::ArrayRef object.""" 64 65 class _iterator: 66 def __init__(self, begin, end): 67 self.cur = begin 68 self.end = end 69 self.count = 0 70 71 def __iter__(self): 72 return self 73 74 def __next__(self): 75 if self.cur == self.end: 76 raise StopIteration 77 count = self.count 78 self.count = self.count + 1 79 cur = self.cur 80 self.cur = self.cur + 1 81 return '[%d]' % count, cur.dereference() 82 83 if sys.version_info.major == 2: 84 next = __next__ 85 86 def __init__(self, val): 87 self.val = val 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 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 319pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport") 320pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter) 321pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter) 322pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter) 323pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter) 324pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter) 325pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter) 326pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter) 327pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter) 328gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) 329