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