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