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']['value']) 133 134 def to_string(self): 135 return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized') 136 137class DenseMapPrinter: 138 "Print a DenseMap" 139 140 class _iterator: 141 def __init__(self, key_info_t, begin, end): 142 self.key_info_t = key_info_t 143 self.cur = begin 144 self.end = end 145 self.advancePastEmptyBuckets() 146 self.first = True 147 148 def __iter__(self): 149 return self 150 151 def advancePastEmptyBuckets(self): 152 # disabled until the comments below can be addressed 153 # keeping as notes/posterity/hints for future contributors 154 return 155 n = self.key_info_t.name 156 is_equal = gdb.parse_and_eval(n + '::isEqual') 157 empty = gdb.parse_and_eval(n + '::getEmptyKey()') 158 tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()') 159 # the following is invalid, GDB fails with: 160 # Python Exception <class 'gdb.error'> Attempt to take address of value 161 # not located in memory. 162 # because isEqual took parameter (for the unsigned long key I was testing) 163 # by const ref, and GDB 164 # It's also not entirely general - we should be accessing the "getFirst()" 165 # member function, not the 'first' member variable, but I've yet to figure 166 # out how to find/call member functions (especially (const) overloaded 167 # ones) on a gdb.Value. 168 while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)): 169 self.cur = self.cur + 1 170 171 def __next__(self): 172 if self.cur == self.end: 173 raise StopIteration 174 cur = self.cur 175 v = cur.dereference()['first' if self.first else 'second'] 176 if not self.first: 177 self.cur = self.cur + 1 178 self.advancePastEmptyBuckets() 179 self.first = True 180 else: 181 self.first = False 182 return 'x', v 183 184 if sys.version_info.major == 2: 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