1# ===----------------------------------------------------------------------===## 2# 3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4# See https://llvm.org/LICENSE.txt for license information. 5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6# 7# ===----------------------------------------------------------------------===## 8"""GDB pretty-printers for libc++. 9 10These should work for objects compiled with either the stable ABI or the unstable ABI. 11""" 12 13from __future__ import print_function 14 15import re 16import gdb 17 18# One under-documented feature of the gdb pretty-printer API 19# is that clients can call any other member of the API 20# before they call to_string. 21# Therefore all self.FIELDs must be set in the pretty-printer's 22# __init__ function. 23 24_void_pointer_type = gdb.lookup_type("void").pointer() 25 26 27_long_int_type = gdb.lookup_type("unsigned long long") 28 29_libcpp_big_endian = False 30 31 32def addr_as_long(addr): 33 return int(addr.cast(_long_int_type)) 34 35 36# The size of a pointer in bytes. 37_pointer_size = _void_pointer_type.sizeof 38 39 40def _remove_cxx_namespace(typename): 41 """Removed libc++ specific namespace from the type. 42 43 Arguments: 44 typename(string): A type, such as std::__u::something. 45 46 Returns: 47 A string without the libc++ specific part, such as std::something. 48 """ 49 50 return re.sub("std::__.*?::", "std::", typename) 51 52 53def _remove_generics(typename): 54 """Remove generics part of the type. Assumes typename is not empty. 55 56 Arguments: 57 typename(string): A type such as std::my_collection<element>. 58 59 Returns: 60 The prefix up to the generic part, such as std::my_collection. 61 """ 62 63 match = re.match("^([^<]+)", typename) 64 return match.group(1) 65 66 67def _cc_field(node): 68 """Previous versions of libcxx had inconsistent field naming naming. Handle 69 both types. 70 """ 71 try: 72 return node["__value_"]["__cc_"] 73 except: 74 return node["__value_"]["__cc"] 75 76 77def _data_field(node): 78 """Previous versions of libcxx had inconsistent field naming naming. Handle 79 both types. 80 """ 81 try: 82 return node["__data_"] 83 except: 84 return node["__data"] 85 86 87def _size_field(node): 88 """Previous versions of libcxx had inconsistent field naming naming. Handle 89 both types. 90 """ 91 try: 92 return node["__size_"] 93 except: 94 return node["__size"] 95 96 97# Some common substitutions on the types to reduce visual clutter (A user who 98# wants to see the actual details can always use print/r). 99_common_substitutions = [ 100 ( 101 "std::basic_string<char, std::char_traits<char>, std::allocator<char> >", 102 "std::string", 103 ), 104 ("std::basic_string_view<char, std::char_traits<char> >", "std::string_view"), 105] 106 107 108def _prettify_typename(gdb_type): 109 """Returns a pretty name for the type, or None if no name can be found. 110 111 Arguments: 112 gdb_type(gdb.Type): A type object. 113 114 Returns: 115 A string, without type_defs, libc++ namespaces, and common substitutions 116 applied. 117 """ 118 119 type_without_typedefs = gdb_type.strip_typedefs() 120 typename = ( 121 type_without_typedefs.name 122 or type_without_typedefs.tag 123 or str(type_without_typedefs) 124 ) 125 result = _remove_cxx_namespace(typename) 126 for find_str, subst_str in _common_substitutions: 127 result = re.sub(find_str, subst_str, result) 128 return result 129 130 131def _typename_for_nth_generic_argument(gdb_type, n): 132 """Returns a pretty string for the nth argument of the given type. 133 134 Arguments: 135 gdb_type(gdb.Type): A type object, such as the one for std::map<int, int> 136 n: The (zero indexed) index of the argument to return. 137 138 Returns: 139 A string for the nth argument, such a "std::string" 140 """ 141 element_type = gdb_type.template_argument(n) 142 return _prettify_typename(element_type) 143 144 145def _typename_with_n_generic_arguments(gdb_type, n): 146 """Return a string for the type with the first n (1, ...) generic args.""" 147 148 base_type = _remove_generics(_prettify_typename(gdb_type)) 149 arg_list = [base_type] 150 template = "%s<" 151 for i in range(n): 152 arg_list.append(_typename_for_nth_generic_argument(gdb_type, i)) 153 template += "%s, " 154 result = (template[:-2] + ">") % tuple(arg_list) 155 return result 156 157 158def _typename_with_first_generic_argument(gdb_type): 159 return _typename_with_n_generic_arguments(gdb_type, 1) 160 161 162class StdTuplePrinter(object): 163 """Print a std::tuple.""" 164 165 class _Children(object): 166 """Class to iterate over the tuple's children.""" 167 168 def __init__(self, val): 169 self.val = val 170 self.child_iter = iter(self.val["__base_"].type.fields()) 171 self.count = 0 172 173 def __iter__(self): 174 return self 175 176 def __next__(self): 177 # child_iter raises StopIteration when appropriate. 178 field_name = next(self.child_iter) 179 child = self.val["__base_"][field_name]["__value_"] 180 self.count += 1 181 return ("[%d]" % self.count, child) 182 183 next = __next__ # Needed for GDB built against Python 2.7. 184 185 def __init__(self, val): 186 self.val = val 187 188 def to_string(self): 189 typename = _remove_generics(_prettify_typename(self.val.type)) 190 if not self.val.type.fields(): 191 return "empty %s" % typename 192 return "%s containing" % typename 193 194 def children(self): 195 if not self.val.type.fields(): 196 return iter(()) 197 return self._Children(self.val) 198 199 200def _get_base_subobject(child_class_value, index=0): 201 """Returns the object's value in the form of the parent class at index. 202 203 This function effectively casts the child_class_value to the base_class's 204 type, but the type-to-cast to is stored in the field at index, and once 205 we know the field, we can just return the data. 206 207 Args: 208 child_class_value: the value to cast 209 index: the parent class index 210 211 Raises: 212 Exception: field at index was not a base-class field. 213 """ 214 215 field = child_class_value.type.fields()[index] 216 if not field.is_base_class: 217 raise Exception("Not a base-class field.") 218 return child_class_value[field] 219 220 221def _value_of_pair_first(value): 222 """Convenience for _get_base_subobject, for the common case.""" 223 return _get_base_subobject(value, 0)["__value_"] 224 225 226class StdStringPrinter(object): 227 """Print a std::string.""" 228 229 def __init__(self, val): 230 self.val = val 231 232 def to_string(self): 233 """Build a python string from the data whether stored inline or separately.""" 234 value_field = _value_of_pair_first(self.val["__r_"]) 235 short_field = value_field["__s"] 236 short_size = short_field["__size_"] 237 if short_field["__is_long_"]: 238 long_field = value_field["__l"] 239 data = long_field["__data_"] 240 size = long_field["__size_"] 241 else: 242 data = short_field["__data_"] 243 size = short_field["__size_"] 244 return data.lazy_string(length=size) 245 246 def display_hint(self): 247 return "string" 248 249 250class StdStringViewPrinter(object): 251 """Print a std::string_view.""" 252 253 def __init__(self, val): 254 self.val = val 255 256 def display_hint(self): 257 return "string" 258 259 def to_string(self): # pylint: disable=g-bad-name 260 """GDB calls this to compute the pretty-printed form.""" 261 262 ptr = _data_field(self.val) 263 ptr = ptr.cast(ptr.type.target().strip_typedefs().pointer()) 264 size = _size_field(self.val) 265 return ptr.lazy_string(length=size) 266 267 268class StdUniquePtrPrinter(object): 269 """Print a std::unique_ptr.""" 270 271 def __init__(self, val): 272 self.val = val 273 self.addr = _value_of_pair_first(self.val["__ptr_"]) 274 self.pointee_type = self.val.type.template_argument(0) 275 276 def to_string(self): 277 typename = _remove_generics(_prettify_typename(self.val.type)) 278 if not self.addr: 279 return "%s is nullptr" % typename 280 return "%s<%s> containing" % ( 281 typename, 282 _remove_generics(_prettify_typename(self.pointee_type)), 283 ) 284 285 def __iter__(self): 286 if self.addr: 287 yield "__ptr_", self.addr.cast(self.pointee_type.pointer()) 288 289 def children(self): 290 return self 291 292 293class StdSharedPointerPrinter(object): 294 """Print a std::shared_ptr.""" 295 296 def __init__(self, val): 297 self.val = val 298 self.addr = self.val["__ptr_"] 299 300 def to_string(self): 301 """Returns self as a string.""" 302 typename = _remove_generics(_prettify_typename(self.val.type)) 303 pointee_type = _remove_generics( 304 _prettify_typename(self.val.type.template_argument(0)) 305 ) 306 if not self.addr: 307 return "%s is nullptr" % typename 308 refcount = self.val["__cntrl_"] 309 if refcount != 0: 310 try: 311 usecount = refcount["__shared_owners_"] + 1 312 weakcount = refcount["__shared_weak_owners_"] 313 if usecount == 0: 314 state = "expired, weak %d" % weakcount 315 else: 316 state = "count %d, weak %d" % (usecount, weakcount) 317 except: 318 # Debug info for a class with virtual functions is emitted 319 # in the same place as its key function. That means that 320 # for std::shared_ptr, __shared_owners_ is emitted into 321 # into libcxx.[so|a] itself, rather than into the shared_ptr 322 # instantiation point. So if libcxx.so was built without 323 # debug info, these fields will be missing. 324 state = "count ?, weak ? (libc++ missing debug info)" 325 return "%s<%s> %s containing" % (typename, pointee_type, state) 326 327 def __iter__(self): 328 if self.addr: 329 yield "__ptr_", self.addr 330 331 def children(self): 332 return self 333 334 335class StdVectorPrinter(object): 336 """Print a std::vector.""" 337 338 class _VectorBoolIterator(object): 339 """Class to iterate over the bool vector's children.""" 340 341 def __init__(self, begin, size, bits_per_word): 342 self.item = begin 343 self.size = size 344 self.bits_per_word = bits_per_word 345 self.count = 0 346 self.offset = 0 347 348 def __iter__(self): 349 return self 350 351 def __next__(self): 352 """Retrieve the next element.""" 353 354 self.count += 1 355 if self.count > self.size: 356 raise StopIteration 357 entry = self.item.dereference() 358 if entry & (1 << self.offset): 359 outbit = 1 360 else: 361 outbit = 0 362 self.offset += 1 363 if self.offset >= self.bits_per_word: 364 self.item += 1 365 self.offset = 0 366 return ("[%d]" % self.count, outbit) 367 368 next = __next__ # Needed for GDB built against Python 2.7. 369 370 class _VectorIterator(object): 371 """Class to iterate over the non-bool vector's children.""" 372 373 def __init__(self, begin, end): 374 self.item = begin 375 self.end = end 376 self.count = 0 377 378 def __iter__(self): 379 return self 380 381 def __next__(self): 382 self.count += 1 383 if self.item == self.end: 384 raise StopIteration 385 entry = self.item.dereference() 386 self.item += 1 387 return ("[%d]" % self.count, entry) 388 389 next = __next__ # Needed for GDB built against Python 2.7. 390 391 def __init__(self, val): 392 """Set val, length, capacity, and iterator for bool and normal vectors.""" 393 self.val = val 394 self.typename = _remove_generics(_prettify_typename(val.type)) 395 begin = self.val["__begin_"] 396 if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL: 397 self.typename += "<bool>" 398 self.length = self.val["__size_"] 399 bits_per_word = self.val["__bits_per_word"] 400 self.capacity = ( 401 _value_of_pair_first(self.val["__cap_alloc_"]) * bits_per_word 402 ) 403 self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word) 404 else: 405 end = self.val["__end_"] 406 self.length = end - begin 407 self.capacity = ( 408 _get_base_subobject(self.val["__end_cap_"])["__value_"] - begin 409 ) 410 self.iterator = self._VectorIterator(begin, end) 411 412 def to_string(self): 413 return "%s of length %d, capacity %d" % ( 414 self.typename, 415 self.length, 416 self.capacity, 417 ) 418 419 def children(self): 420 return self.iterator 421 422 def display_hint(self): 423 return "array" 424 425 426class StdBitsetPrinter(object): 427 """Print a std::bitset.""" 428 429 def __init__(self, val): 430 self.val = val 431 self.n_words = int(self.val["__n_words"]) 432 self.bits_per_word = int(self.val["__bits_per_word"]) 433 self.bit_count = self.val.type.template_argument(0) 434 if self.n_words == 1: 435 self.values = [int(self.val["__first_"])] 436 else: 437 self.values = [ 438 int(self.val["__first_"][index]) for index in range(self.n_words) 439 ] 440 441 def to_string(self): 442 typename = _prettify_typename(self.val.type) 443 return "%s" % typename 444 445 def _list_it(self): 446 for bit in range(self.bit_count): 447 word = bit // self.bits_per_word 448 word_bit = bit % self.bits_per_word 449 if self.values[word] & (1 << word_bit): 450 yield ("[%d]" % bit, 1) 451 452 def __iter__(self): 453 return self._list_it() 454 455 def children(self): 456 return self 457 458 459class StdDequePrinter(object): 460 """Print a std::deque.""" 461 462 def __init__(self, val): 463 self.val = val 464 self.size = int(_value_of_pair_first(val["__size_"])) 465 self.start_ptr = self.val["__map_"]["__begin_"] 466 self.first_block_start_index = int(self.val["__start_"]) 467 self.node_type = self.start_ptr.type 468 self.block_size = self._calculate_block_size(val.type.template_argument(0)) 469 470 def _calculate_block_size(self, element_type): 471 """Calculates the number of elements in a full block.""" 472 size = element_type.sizeof 473 # Copied from struct __deque_block_size implementation of libcxx. 474 return 4096 / size if size < 256 else 16 475 476 def _bucket_it(self, start_addr, start_index, end_index): 477 for i in range(start_index, end_index): 478 yield i, (start_addr.dereference() + i).dereference() 479 480 def _list_it(self): 481 """Primary iteration worker.""" 482 num_emitted = 0 483 current_addr = self.start_ptr 484 start_index = self.first_block_start_index 485 while num_emitted < self.size: 486 end_index = min(start_index + self.size - num_emitted, self.block_size) 487 for _, elem in self._bucket_it(current_addr, start_index, end_index): 488 yield "", elem 489 num_emitted += end_index - start_index 490 current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size).cast( 491 self.node_type 492 ) 493 start_index = 0 494 495 def to_string(self): 496 typename = _remove_generics(_prettify_typename(self.val.type)) 497 if self.size: 498 return "%s with %d elements" % (typename, self.size) 499 return "%s is empty" % typename 500 501 def __iter__(self): 502 return self._list_it() 503 504 def children(self): 505 return self 506 507 def display_hint(self): 508 return "array" 509 510 511class StdListPrinter(object): 512 """Print a std::list.""" 513 514 def __init__(self, val): 515 self.val = val 516 size_alloc_field = self.val["__size_alloc_"] 517 self.size = int(_value_of_pair_first(size_alloc_field)) 518 dummy_node = self.val["__end_"] 519 self.nodetype = gdb.lookup_type( 520 re.sub( 521 "__list_node_base", "__list_node", str(dummy_node.type.strip_typedefs()) 522 ) 523 ).pointer() 524 self.first_node = dummy_node["__next_"] 525 526 def to_string(self): 527 typename = _remove_generics(_prettify_typename(self.val.type)) 528 if self.size: 529 return "%s with %d elements" % (typename, self.size) 530 return "%s is empty" % typename 531 532 def _list_iter(self): 533 current_node = self.first_node 534 for _ in range(self.size): 535 yield "", current_node.cast(self.nodetype).dereference()["__value_"] 536 current_node = current_node.dereference()["__next_"] 537 538 def __iter__(self): 539 return self._list_iter() 540 541 def children(self): 542 return self if self.nodetype else iter(()) 543 544 def display_hint(self): 545 return "array" 546 547 548class StdQueueOrStackPrinter(object): 549 """Print a std::queue or std::stack.""" 550 551 def __init__(self, val): 552 self.val = val 553 self.underlying = val["c"] 554 555 def to_string(self): 556 typename = _remove_generics(_prettify_typename(self.val.type)) 557 return "%s wrapping" % typename 558 559 def children(self): 560 return iter([("", self.underlying)]) 561 562 def display_hint(self): 563 return "array" 564 565 566class StdPriorityQueuePrinter(object): 567 """Print a std::priority_queue.""" 568 569 def __init__(self, val): 570 self.val = val 571 self.underlying = val["c"] 572 573 def to_string(self): 574 # TODO(tamur): It would be nice to print the top element. The technical 575 # difficulty is that, the implementation refers to the underlying 576 # container, which is a generic class. libstdcxx pretty printers do not 577 # print the top element. 578 typename = _remove_generics(_prettify_typename(self.val.type)) 579 return "%s wrapping" % typename 580 581 def children(self): 582 return iter([("", self.underlying)]) 583 584 def display_hint(self): 585 return "array" 586 587 588class RBTreeUtils(object): 589 """Utility class for std::(multi)map, and std::(multi)set and iterators.""" 590 591 def __init__(self, cast_type, root): 592 self.cast_type = cast_type 593 self.root = root 594 595 def left_child(self, node): 596 result = node.cast(self.cast_type).dereference()["__left_"] 597 return result 598 599 def right_child(self, node): 600 result = node.cast(self.cast_type).dereference()["__right_"] 601 return result 602 603 def parent(self, node): 604 """Return the parent of node, if it exists.""" 605 # If this is the root, then from the algorithm's point of view, it has no 606 # parent. 607 if node == self.root: 608 return None 609 610 # We don't have enough information to tell if this is the end_node (which 611 # doesn't have a __parent_ field), or the root (which doesn't have a parent 612 # from the algorithm's point of view), so cast_type may not be correct for 613 # this particular node. Use heuristics. 614 615 # The end_node's left child is the root. Note that when printing interators 616 # in isolation, the root is unknown. 617 if self.left_child(node) == self.root: 618 return None 619 620 parent = node.cast(self.cast_type).dereference()["__parent_"] 621 # If the value at the offset of __parent_ doesn't look like a valid pointer, 622 # then assume that node is the end_node (and therefore has no parent). 623 # End_node type has a pointer embedded, so should have pointer alignment. 624 if addr_as_long(parent) % _void_pointer_type.alignof: 625 return None 626 # This is ugly, but the only other option is to dereference an invalid 627 # pointer. 0x8000 is fairly arbitrary, but has had good results in 628 # practice. If there was a way to tell if a pointer is invalid without 629 # actually dereferencing it and spewing error messages, that would be ideal. 630 if parent < 0x8000: 631 return None 632 return parent 633 634 def is_left_child(self, node): 635 parent = self.parent(node) 636 return parent is not None and self.left_child(parent) == node 637 638 def is_right_child(self, node): 639 parent = self.parent(node) 640 return parent is not None and self.right_child(parent) == node 641 642 643class AbstractRBTreePrinter(object): 644 """Abstract super class for std::(multi)map, and std::(multi)set.""" 645 646 def __init__(self, val): 647 self.val = val 648 tree = self.val["__tree_"] 649 self.size = int(_value_of_pair_first(tree["__pair3_"])) 650 dummy_root = tree["__pair1_"] 651 root = _value_of_pair_first(dummy_root)["__left_"] 652 cast_type = self._init_cast_type(val.type) 653 self.util = RBTreeUtils(cast_type, root) 654 655 def _get_key_value(self, node): 656 """Subclasses should override to return a list of values to yield.""" 657 raise NotImplementedError 658 659 def _traverse(self): 660 """Traverses the binary search tree in order.""" 661 current = self.util.root 662 skip_left_child = False 663 while True: 664 if not skip_left_child and self.util.left_child(current): 665 current = self.util.left_child(current) 666 continue 667 skip_left_child = False 668 for key_value in self._get_key_value(current): 669 yield "", key_value 670 right_child = self.util.right_child(current) 671 if right_child: 672 current = right_child 673 continue 674 while self.util.is_right_child(current): 675 current = self.util.parent(current) 676 if self.util.is_left_child(current): 677 current = self.util.parent(current) 678 skip_left_child = True 679 continue 680 break 681 682 def __iter__(self): 683 return self._traverse() 684 685 def children(self): 686 return self if self.util.cast_type and self.size > 0 else iter(()) 687 688 def to_string(self): 689 typename = _remove_generics(_prettify_typename(self.val.type)) 690 if self.size: 691 return "%s with %d elements" % (typename, self.size) 692 return "%s is empty" % typename 693 694 695class StdMapPrinter(AbstractRBTreePrinter): 696 """Print a std::map or std::multimap.""" 697 698 def _init_cast_type(self, val_type): 699 map_it_type = gdb.lookup_type( 700 str(val_type.strip_typedefs()) + "::iterator" 701 ).strip_typedefs() 702 tree_it_type = map_it_type.template_argument(0) 703 node_ptr_type = tree_it_type.template_argument(1) 704 return node_ptr_type 705 706 def display_hint(self): 707 return "map" 708 709 def _get_key_value(self, node): 710 key_value = _cc_field(node.cast(self.util.cast_type).dereference()) 711 return [key_value["first"], key_value["second"]] 712 713 714class StdSetPrinter(AbstractRBTreePrinter): 715 """Print a std::set.""" 716 717 def _init_cast_type(self, val_type): 718 set_it_type = gdb.lookup_type( 719 str(val_type.strip_typedefs()) + "::iterator" 720 ).strip_typedefs() 721 node_ptr_type = set_it_type.template_argument(1) 722 return node_ptr_type 723 724 def display_hint(self): 725 return "array" 726 727 def _get_key_value(self, node): 728 key_value = node.cast(self.util.cast_type).dereference()["__value_"] 729 return [key_value] 730 731 732class AbstractRBTreeIteratorPrinter(object): 733 """Abstract super class for std::(multi)map, and std::(multi)set iterator.""" 734 735 def _initialize(self, val, typename): 736 self.typename = typename 737 self.val = val 738 self.addr = self.val["__ptr_"] 739 cast_type = self.val.type.template_argument(1) 740 self.util = RBTreeUtils(cast_type, None) 741 if self.addr: 742 self.node = self.addr.cast(cast_type).dereference() 743 744 def _is_valid_node(self): 745 if not self.util.parent(self.addr): 746 return False 747 return self.util.is_left_child(self.addr) or self.util.is_right_child(self.addr) 748 749 def to_string(self): 750 if not self.addr: 751 return "%s is nullptr" % self.typename 752 return "%s " % self.typename 753 754 def _get_node_value(self, node): 755 raise NotImplementedError 756 757 def __iter__(self): 758 addr_str = "[%s]" % str(self.addr) 759 if not self._is_valid_node(): 760 yield addr_str, " end()" 761 else: 762 yield addr_str, self._get_node_value(self.node) 763 764 def children(self): 765 return self if self.addr else iter(()) 766 767 768class MapIteratorPrinter(AbstractRBTreeIteratorPrinter): 769 """Print a std::(multi)map iterator.""" 770 771 def __init__(self, val): 772 self._initialize(val["__i_"], _remove_generics(_prettify_typename(val.type))) 773 774 def _get_node_value(self, node): 775 return _cc_field(node) 776 777 778class SetIteratorPrinter(AbstractRBTreeIteratorPrinter): 779 """Print a std::(multi)set iterator.""" 780 781 def __init__(self, val): 782 self._initialize(val, _remove_generics(_prettify_typename(val.type))) 783 784 def _get_node_value(self, node): 785 return node["__value_"] 786 787 788class StdFposPrinter(object): 789 """Print a std::fpos or std::streampos.""" 790 791 def __init__(self, val): 792 self.val = val 793 794 def to_string(self): 795 typename = _remove_generics(_prettify_typename(self.val.type)) 796 offset = self.val["__off_"] 797 state = self.val["__st_"] 798 799 state_fields = [] 800 if state.type.code == gdb.TYPE_CODE_STRUCT: 801 state_fields = [f.name for f in state.type.fields()] 802 803 state_string = "" 804 if "__count" in state_fields and "__value" in state_fields: 805 count = state["__count"] 806 value = state["__value"]["__wch"] 807 state_string = " with state: {count:%s value:%s}" % (count, value) 808 809 return "%s with stream offset:%s%s" % (typename, offset, state_string) 810 811 812class AbstractUnorderedCollectionPrinter(object): 813 """Abstract super class for std::unordered_(multi)[set|map].""" 814 815 def __init__(self, val): 816 self.val = val 817 self.table = val["__table_"] 818 self.sentinel = self.table["__p1_"] 819 self.size = int(_value_of_pair_first(self.table["__p2_"])) 820 node_base_type = self.sentinel.type.template_argument(0) 821 self.cast_type = node_base_type.template_argument(0) 822 823 def _list_it(self, sentinel_ptr): 824 next_ptr = _value_of_pair_first(sentinel_ptr)["__next_"] 825 while str(next_ptr.cast(_void_pointer_type)) != "0x0": 826 next_val = next_ptr.cast(self.cast_type).dereference() 827 for key_value in self._get_key_value(next_val): 828 yield "", key_value 829 next_ptr = next_val["__next_"] 830 831 def to_string(self): 832 typename = _remove_generics(_prettify_typename(self.val.type)) 833 if self.size: 834 return "%s with %d elements" % (typename, self.size) 835 return "%s is empty" % typename 836 837 def _get_key_value(self, node): 838 """Subclasses should override to return a list of values to yield.""" 839 raise NotImplementedError 840 841 def children(self): 842 return self if self.cast_type and self.size > 0 else iter(()) 843 844 def __iter__(self): 845 return self._list_it(self.sentinel) 846 847 848class StdUnorderedSetPrinter(AbstractUnorderedCollectionPrinter): 849 """Print a std::unordered_(multi)set.""" 850 851 def _get_key_value(self, node): 852 return [node["__value_"]] 853 854 def display_hint(self): 855 return "array" 856 857 858class StdUnorderedMapPrinter(AbstractUnorderedCollectionPrinter): 859 """Print a std::unordered_(multi)map.""" 860 861 def _get_key_value(self, node): 862 key_value = _cc_field(node) 863 return [key_value["first"], key_value["second"]] 864 865 def display_hint(self): 866 return "map" 867 868 869class AbstractHashMapIteratorPrinter(object): 870 """Abstract class for unordered collection iterators.""" 871 872 def _initialize(self, val, addr): 873 self.val = val 874 self.typename = _remove_generics(_prettify_typename(self.val.type)) 875 self.addr = addr 876 if self.addr: 877 self.node = self.addr.cast(self.cast_type).dereference() 878 879 def _get_key_value(self): 880 """Subclasses should override to return a list of values to yield.""" 881 raise NotImplementedError 882 883 def to_string(self): 884 if not self.addr: 885 return "%s = end()" % self.typename 886 return "%s " % self.typename 887 888 def children(self): 889 return self if self.addr else iter(()) 890 891 def __iter__(self): 892 for key_value in self._get_key_value(): 893 yield "", key_value 894 895 896class StdUnorderedSetIteratorPrinter(AbstractHashMapIteratorPrinter): 897 """Print a std::(multi)set iterator.""" 898 899 def __init__(self, val): 900 self.cast_type = val.type.template_argument(0) 901 self._initialize(val, val["__node_"]) 902 903 def _get_key_value(self): 904 return [self.node["__value_"]] 905 906 def display_hint(self): 907 return "array" 908 909 910class StdUnorderedMapIteratorPrinter(AbstractHashMapIteratorPrinter): 911 """Print a std::(multi)map iterator.""" 912 913 def __init__(self, val): 914 self.cast_type = val.type.template_argument(0).template_argument(0) 915 self._initialize(val, val["__i_"]["__node_"]) 916 917 def _get_key_value(self): 918 key_value = _cc_field(self.node) 919 return [key_value["first"], key_value["second"]] 920 921 def display_hint(self): 922 return "map" 923 924 925def _remove_std_prefix(typename): 926 match = re.match("^std::(.+)", typename) 927 return match.group(1) if match is not None else "" 928 929 930class LibcxxPrettyPrinter(object): 931 """PrettyPrinter object so gdb-commands like 'info pretty-printers' work.""" 932 933 def __init__(self, name): 934 super(LibcxxPrettyPrinter, self).__init__() 935 self.name = name 936 self.enabled = True 937 938 self.lookup = { 939 "basic_string": StdStringPrinter, 940 "string": StdStringPrinter, 941 "string_view": StdStringViewPrinter, 942 "tuple": StdTuplePrinter, 943 "unique_ptr": StdUniquePtrPrinter, 944 "shared_ptr": StdSharedPointerPrinter, 945 "weak_ptr": StdSharedPointerPrinter, 946 "bitset": StdBitsetPrinter, 947 "deque": StdDequePrinter, 948 "list": StdListPrinter, 949 "queue": StdQueueOrStackPrinter, 950 "stack": StdQueueOrStackPrinter, 951 "priority_queue": StdPriorityQueuePrinter, 952 "map": StdMapPrinter, 953 "multimap": StdMapPrinter, 954 "set": StdSetPrinter, 955 "multiset": StdSetPrinter, 956 "vector": StdVectorPrinter, 957 "__map_iterator": MapIteratorPrinter, 958 "__map_const_iterator": MapIteratorPrinter, 959 "__tree_iterator": SetIteratorPrinter, 960 "__tree_const_iterator": SetIteratorPrinter, 961 "fpos": StdFposPrinter, 962 "unordered_set": StdUnorderedSetPrinter, 963 "unordered_multiset": StdUnorderedSetPrinter, 964 "unordered_map": StdUnorderedMapPrinter, 965 "unordered_multimap": StdUnorderedMapPrinter, 966 "__hash_map_iterator": StdUnorderedMapIteratorPrinter, 967 "__hash_map_const_iterator": StdUnorderedMapIteratorPrinter, 968 "__hash_iterator": StdUnorderedSetIteratorPrinter, 969 "__hash_const_iterator": StdUnorderedSetIteratorPrinter, 970 } 971 972 self.subprinters = [] 973 for name, subprinter in self.lookup.items(): 974 # Subprinters and names are used only for the rarely used command "info 975 # pretty" (and related), so the name of the first data structure it prints 976 # is a reasonable choice. 977 if subprinter not in self.subprinters: 978 subprinter.name = name 979 self.subprinters.append(subprinter) 980 981 def __call__(self, val): 982 """Return the pretty printer for a val, if the type is supported.""" 983 984 # Do not handle any type that is not a struct/class. 985 if val.type.strip_typedefs().code != gdb.TYPE_CODE_STRUCT: 986 return None 987 988 # Don't attempt types known to be inside libstdcxx. 989 typename = val.type.name or val.type.tag or str(val.type) 990 match = re.match("^std::(__.*?)::", typename) 991 if match is not None and match.group(1) in [ 992 "__cxx1998", 993 "__debug", 994 "__7", 995 "__g", 996 ]: 997 return None 998 999 # Handle any using declarations or other typedefs. 1000 typename = _prettify_typename(val.type) 1001 if not typename: 1002 return None 1003 without_generics = _remove_generics(typename) 1004 lookup_name = _remove_std_prefix(without_generics) 1005 if lookup_name in self.lookup: 1006 return self.lookup[lookup_name](val) 1007 return None 1008 1009 1010_libcxx_printer_name = "libcxx_pretty_printer" 1011 1012 1013# These are called for every binary object file, which could be thousands in 1014# certain pathological cases. Limit our pretty printers to the progspace. 1015def _register_libcxx_printers(event): 1016 progspace = event.new_objfile.progspace 1017 # It would be ideal to get the endianness at print time, but 1018 # gdb.execute clears gdb's internal wrap buffer, removing any values 1019 # already generated as part of a larger data structure, and there is 1020 # no python api to get the endianness. Mixed-endianness debugging 1021 # rare enough that this workaround should be adequate. 1022 _libcpp_big_endian = "big endian" in gdb.execute("show endian", to_string=True) 1023 1024 if not getattr(progspace, _libcxx_printer_name, False): 1025 print("Loading libc++ pretty-printers.") 1026 gdb.printing.register_pretty_printer( 1027 progspace, LibcxxPrettyPrinter(_libcxx_printer_name) 1028 ) 1029 setattr(progspace, _libcxx_printer_name, True) 1030 1031 1032def _unregister_libcxx_printers(event): 1033 progspace = event.progspace 1034 if getattr(progspace, _libcxx_printer_name, False): 1035 for printer in progspace.pretty_printers: 1036 if getattr(printer, "name", "none") == _libcxx_printer_name: 1037 progspace.pretty_printers.remove(printer) 1038 setattr(progspace, _libcxx_printer_name, False) 1039 break 1040 1041 1042def register_libcxx_printer_loader(): 1043 """Register event handlers to load libc++ pretty-printers.""" 1044 gdb.events.new_objfile.connect(_register_libcxx_printers) 1045 gdb.events.clear_objfiles.connect(_unregister_libcxx_printers) 1046