1# Pretty-printers for libstdc++. 2 3# Copyright (C) 2008-2020 Free Software Foundation, Inc. 4 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18import gdb 19import itertools 20import re 21import sys, os, errno 22 23### Python 2 + Python 3 compatibility code 24 25# Resources about compatibility: 26# 27# * <http://pythonhosted.org/six/>: Documentation of the "six" module 28 29# FIXME: The handling of e.g. std::basic_string (at least on char) 30# probably needs updating to work with Python 3's new string rules. 31# 32# In particular, Python 3 has a separate type (called byte) for 33# bytestrings, and a special b"" syntax for the byte literals; the old 34# str() type has been redefined to always store Unicode text. 35# 36# We probably can't do much about this until this GDB PR is addressed: 37# <https://sourceware.org/bugzilla/show_bug.cgi?id=17138> 38 39if sys.version_info[0] > 2: 40 ### Python 3 stuff 41 Iterator = object 42 # Python 3 folds these into the normal functions. 43 imap = map 44 izip = zip 45 # Also, int subsumes long 46 long = int 47else: 48 ### Python 2 stuff 49 class Iterator: 50 """Compatibility mixin for iterators 51 52 Instead of writing next() methods for iterators, write 53 __next__() methods and use this mixin to make them work in 54 Python 2 as well as Python 3. 55 56 Idea stolen from the "six" documentation: 57 <http://pythonhosted.org/six/#six.Iterator> 58 """ 59 60 def next(self): 61 return self.__next__() 62 63 # In Python 2, we still need these from itertools 64 from itertools import imap, izip 65 66# Try to use the new-style pretty-printing if available. 67_use_gdb_pp = True 68try: 69 import gdb.printing 70except ImportError: 71 _use_gdb_pp = False 72 73# Try to install type-printers. 74_use_type_printing = False 75try: 76 import gdb.types 77 if hasattr(gdb.types, 'TypePrinter'): 78 _use_type_printing = True 79except ImportError: 80 pass 81 82# Starting with the type ORIG, search for the member type NAME. This 83# handles searching upward through superclasses. This is needed to 84# work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615. 85def find_type(orig, name): 86 typ = orig.strip_typedefs() 87 while True: 88 # Use Type.tag to ignore cv-qualifiers. PR 67440. 89 search = '%s::%s' % (typ.tag, name) 90 try: 91 return gdb.lookup_type(search) 92 except RuntimeError: 93 pass 94 # The type was not found, so try the superclass. We only need 95 # to check the first superclass, so we don't bother with 96 # anything fancier here. 97 fields = typ.fields() 98 if len(fields) and fields[0].is_base_class: 99 typ = fields[0].type 100 else: 101 raise ValueError("Cannot find type %s::%s" % (str(orig), name)) 102 103_versioned_namespace = '__8::' 104 105def lookup_templ_spec(templ, *args): 106 """ 107 Lookup template specialization templ<args...> 108 """ 109 t = '{}<{}>'.format(templ, ', '.join([str(a) for a in args])) 110 try: 111 return gdb.lookup_type(t) 112 except gdb.error as e: 113 # Type not found, try again in versioned namespace. 114 global _versioned_namespace 115 if _versioned_namespace and _versioned_namespace not in templ: 116 t = t.replace('::', '::' + _versioned_namespace, 1) 117 try: 118 return gdb.lookup_type(t) 119 except gdb.error: 120 # If that also fails, rethrow the original exception 121 pass 122 raise e 123 124# Use this to find container node types instead of find_type, 125# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91997 for details. 126def lookup_node_type(nodename, containertype): 127 """ 128 Lookup specialization of template NODENAME corresponding to CONTAINERTYPE. 129 e.g. if NODENAME is '_List_node' and CONTAINERTYPE is std::list<int> 130 then return the type std::_List_node<int>. 131 Returns None if not found. 132 """ 133 # If nodename is unqualified, assume it's in namespace std. 134 if '::' not in nodename: 135 nodename = 'std::' + nodename 136 try: 137 valtype = find_type(containertype, 'value_type') 138 except: 139 valtype = containertype.template_argument(0) 140 valtype = valtype.strip_typedefs() 141 try: 142 return lookup_templ_spec(nodename, valtype) 143 except gdb.error as e: 144 # For debug mode containers the node is in std::__cxx1998. 145 if is_member_of_namespace(nodename, 'std'): 146 if is_member_of_namespace(containertype, 'std::__cxx1998', 147 'std::__debug', '__gnu_debug'): 148 nodename = nodename.replace('::', '::__cxx1998::', 1) 149 try: 150 return lookup_templ_spec(nodename, valtype) 151 except gdb.error: 152 pass 153 return None 154 155def is_member_of_namespace(typ, *namespaces): 156 """ 157 Test whether a type is a member of one of the specified namespaces. 158 The type can be specified as a string or a gdb.Type object. 159 """ 160 if type(typ) is gdb.Type: 161 typ = str(typ) 162 typ = strip_versioned_namespace(typ) 163 for namespace in namespaces: 164 if typ.startswith(namespace + '::'): 165 return True 166 return False 167 168def is_specialization_of(x, template_name): 169 "Test if a type is a given template instantiation." 170 global _versioned_namespace 171 if type(x) is gdb.Type: 172 x = x.tag 173 if _versioned_namespace: 174 return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), x) is not None 175 return re.match('^std::%s<.*>$' % template_name, x) is not None 176 177def strip_versioned_namespace(typename): 178 global _versioned_namespace 179 if _versioned_namespace: 180 return typename.replace(_versioned_namespace, '') 181 return typename 182 183def strip_inline_namespaces(type_str): 184 "Remove known inline namespaces from the canonical name of a type." 185 type_str = strip_versioned_namespace(type_str) 186 type_str = type_str.replace('std::__cxx11::', 'std::') 187 expt_ns = 'std::experimental::' 188 for lfts_ns in ('fundamentals_v1', 'fundamentals_v2'): 189 type_str = type_str.replace(expt_ns+lfts_ns+'::', expt_ns) 190 fs_ns = expt_ns + 'filesystem::' 191 type_str = type_str.replace(fs_ns+'v1::', fs_ns) 192 return type_str 193 194def get_template_arg_list(type_obj): 195 "Return a type's template arguments as a list" 196 n = 0 197 template_args = [] 198 while True: 199 try: 200 template_args.append(type_obj.template_argument(n)) 201 except: 202 return template_args 203 n += 1 204 205class SmartPtrIterator(Iterator): 206 "An iterator for smart pointer types with a single 'child' value" 207 208 def __init__(self, val): 209 self.val = val 210 211 def __iter__(self): 212 return self 213 214 def __next__(self): 215 if self.val is None: 216 raise StopIteration 217 self.val, val = None, self.val 218 return ('get()', val) 219 220class SharedPointerPrinter: 221 "Print a shared_ptr or weak_ptr" 222 223 def __init__ (self, typename, val): 224 self.typename = strip_versioned_namespace(typename) 225 self.val = val 226 self.pointer = val['_M_ptr'] 227 228 def children (self): 229 return SmartPtrIterator(self.pointer) 230 231 def to_string (self): 232 state = 'empty' 233 refcounts = self.val['_M_refcount']['_M_pi'] 234 if refcounts != 0: 235 usecount = refcounts['_M_use_count'] 236 weakcount = refcounts['_M_weak_count'] 237 if usecount == 0: 238 state = 'expired, weak count %d' % weakcount 239 else: 240 state = 'use count %d, weak count %d' % (usecount, weakcount - 1) 241 return '%s<%s> (%s)' % (self.typename, str(self.val.type.template_argument(0)), state) 242 243def _tuple_impl_get(val): 244 "Return the tuple element stored in a _Tuple_impl<N, T> base class." 245 bases = val.type.fields() 246 if not bases[-1].is_base_class: 247 raise ValueError("Unsupported implementation for std::tuple: %s" % str(val.type)) 248 # Get the _Head_base<N, T> base class: 249 head_base = val.cast(bases[-1].type) 250 fields = head_base.type.fields() 251 if len(fields) == 0: 252 raise ValueError("Unsupported implementation for std::tuple: %s" % str(val.type)) 253 if fields[0].name == '_M_head_impl': 254 # The tuple element is the _Head_base::_M_head_impl data member. 255 return head_base['_M_head_impl'] 256 elif fields[0].is_base_class: 257 # The tuple element is an empty base class of _Head_base. 258 # Cast to that empty base class. 259 return head_base.cast(fields[0].type) 260 else: 261 raise ValueError("Unsupported implementation for std::tuple: %s" % str(val.type)) 262 263def tuple_get(n, val): 264 "Return the result of std::get<n>(val) on a std::tuple" 265 tuple_size = len(get_template_arg_list(val.type)) 266 if n > tuple_size: 267 raise ValueError("Out of range index for std::get<N> on std::tuple") 268 # Get the first _Tuple_impl<0, T...> base class: 269 node = val.cast(val.type.fields()[0].type) 270 while n > 0: 271 # Descend through the base classes until the Nth one. 272 node = node.cast(node.type.fields()[0].type) 273 n -= 1 274 return _tuple_impl_get(node) 275 276def unique_ptr_get(val): 277 "Return the result of val.get() on a std::unique_ptr" 278 # std::unique_ptr<T, D> contains a std::tuple<D::pointer, D>, 279 # either as a direct data member _M_t (the old implementation) 280 # or within a data member of type __uniq_ptr_data. 281 impl_type = val.type.fields()[0].type.strip_typedefs() 282 # Check for new implementations first: 283 if is_specialization_of(impl_type, '__uniq_ptr_data') \ 284 or is_specialization_of(impl_type, '__uniq_ptr_impl'): 285 tuple_member = val['_M_t']['_M_t'] 286 elif is_specialization_of(impl_type, 'tuple'): 287 tuple_member = val['_M_t'] 288 else: 289 raise ValueError("Unsupported implementation for unique_ptr: %s" % str(impl_type)) 290 return tuple_get(0, tuple_member) 291 292class UniquePointerPrinter: 293 "Print a unique_ptr" 294 295 def __init__ (self, typename, val): 296 self.val = val 297 298 def children (self): 299 return SmartPtrIterator(unique_ptr_get(self.val)) 300 301 def to_string (self): 302 return ('std::unique_ptr<%s>' % (str(self.val.type.template_argument(0)))) 303 304def get_value_from_aligned_membuf(buf, valtype): 305 """Returns the value held in a __gnu_cxx::__aligned_membuf.""" 306 return buf['_M_storage'].address.cast(valtype.pointer()).dereference() 307 308def get_value_from_list_node(node): 309 """Returns the value held in an _List_node<_Val>""" 310 try: 311 member = node.type.fields()[1].name 312 if member == '_M_data': 313 # C++03 implementation, node contains the value as a member 314 return node['_M_data'] 315 elif member == '_M_storage': 316 # C++11 implementation, node stores value in __aligned_membuf 317 valtype = node.type.template_argument(0) 318 return get_value_from_aligned_membuf(node['_M_storage'], valtype) 319 except: 320 pass 321 raise ValueError("Unsupported implementation for %s" % str(node.type)) 322 323class StdListPrinter: 324 "Print a std::list" 325 326 class _iterator(Iterator): 327 def __init__(self, nodetype, head): 328 self.nodetype = nodetype 329 self.base = head['_M_next'] 330 self.head = head.address 331 self.count = 0 332 333 def __iter__(self): 334 return self 335 336 def __next__(self): 337 if self.base == self.head: 338 raise StopIteration 339 elt = self.base.cast(self.nodetype).dereference() 340 self.base = elt['_M_next'] 341 count = self.count 342 self.count = self.count + 1 343 val = get_value_from_list_node(elt) 344 return ('[%d]' % count, val) 345 346 def __init__(self, typename, val): 347 self.typename = strip_versioned_namespace(typename) 348 self.val = val 349 350 def children(self): 351 nodetype = lookup_node_type('_List_node', self.val.type).pointer() 352 return self._iterator(nodetype, self.val['_M_impl']['_M_node']) 353 354 def to_string(self): 355 headnode = self.val['_M_impl']['_M_node'] 356 if headnode['_M_next'] == headnode.address: 357 return 'empty %s' % (self.typename) 358 return '%s' % (self.typename) 359 360class NodeIteratorPrinter: 361 def __init__(self, typename, val, contname, nodename): 362 self.val = val 363 self.typename = typename 364 self.contname = contname 365 self.nodetype = lookup_node_type(nodename, val.type) 366 367 def to_string(self): 368 if not self.val['_M_node']: 369 return 'non-dereferenceable iterator for std::%s' % (self.contname) 370 node = self.val['_M_node'].cast(self.nodetype.pointer()).dereference() 371 return str(get_value_from_list_node(node)) 372 373class StdListIteratorPrinter(NodeIteratorPrinter): 374 "Print std::list::iterator" 375 376 def __init__(self, typename, val): 377 NodeIteratorPrinter.__init__(self, typename, val, 'list', '_List_node') 378 379class StdFwdListIteratorPrinter(NodeIteratorPrinter): 380 "Print std::forward_list::iterator" 381 382 def __init__(self, typename, val): 383 NodeIteratorPrinter.__init__(self, typename, val, 'forward_list', 384 '_Fwd_list_node') 385 386class StdSlistPrinter: 387 "Print a __gnu_cxx::slist" 388 389 class _iterator(Iterator): 390 def __init__(self, nodetype, head): 391 self.nodetype = nodetype 392 self.base = head['_M_head']['_M_next'] 393 self.count = 0 394 395 def __iter__(self): 396 return self 397 398 def __next__(self): 399 if self.base == 0: 400 raise StopIteration 401 elt = self.base.cast(self.nodetype).dereference() 402 self.base = elt['_M_next'] 403 count = self.count 404 self.count = self.count + 1 405 return ('[%d]' % count, elt['_M_data']) 406 407 def __init__(self, typename, val): 408 self.val = val 409 410 def children(self): 411 nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type) 412 return self._iterator(nodetype.pointer(), self.val) 413 414 def to_string(self): 415 if self.val['_M_head']['_M_next'] == 0: 416 return 'empty __gnu_cxx::slist' 417 return '__gnu_cxx::slist' 418 419class StdSlistIteratorPrinter: 420 "Print __gnu_cxx::slist::iterator" 421 422 def __init__(self, typename, val): 423 self.val = val 424 425 def to_string(self): 426 if not self.val['_M_node']: 427 return 'non-dereferenceable iterator for __gnu_cxx::slist' 428 nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type).pointer() 429 return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data']) 430 431class StdVectorPrinter: 432 "Print a std::vector" 433 434 class _iterator(Iterator): 435 def __init__ (self, start, finish, bitvec): 436 self.bitvec = bitvec 437 if bitvec: 438 self.item = start['_M_p'] 439 self.so = start['_M_offset'] 440 self.finish = finish['_M_p'] 441 self.fo = finish['_M_offset'] 442 itype = self.item.dereference().type 443 self.isize = 8 * itype.sizeof 444 else: 445 self.item = start 446 self.finish = finish 447 self.count = 0 448 449 def __iter__(self): 450 return self 451 452 def __next__(self): 453 count = self.count 454 self.count = self.count + 1 455 if self.bitvec: 456 if self.item == self.finish and self.so >= self.fo: 457 raise StopIteration 458 elt = bool(self.item.dereference() & (1 << self.so)) 459 self.so = self.so + 1 460 if self.so >= self.isize: 461 self.item = self.item + 1 462 self.so = 0 463 return ('[%d]' % count, elt) 464 else: 465 if self.item == self.finish: 466 raise StopIteration 467 elt = self.item.dereference() 468 self.item = self.item + 1 469 return ('[%d]' % count, elt) 470 471 def __init__(self, typename, val): 472 self.typename = strip_versioned_namespace(typename) 473 self.val = val 474 self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL 475 476 def children(self): 477 return self._iterator(self.val['_M_impl']['_M_start'], 478 self.val['_M_impl']['_M_finish'], 479 self.is_bool) 480 481 def to_string(self): 482 start = self.val['_M_impl']['_M_start'] 483 finish = self.val['_M_impl']['_M_finish'] 484 end = self.val['_M_impl']['_M_end_of_storage'] 485 if self.is_bool: 486 start = self.val['_M_impl']['_M_start']['_M_p'] 487 so = self.val['_M_impl']['_M_start']['_M_offset'] 488 finish = self.val['_M_impl']['_M_finish']['_M_p'] 489 fo = self.val['_M_impl']['_M_finish']['_M_offset'] 490 itype = start.dereference().type 491 bl = 8 * itype.sizeof 492 length = (bl - so) + bl * ((finish - start) - 1) + fo 493 capacity = bl * (end - start) 494 return ('%s<bool> of length %d, capacity %d' 495 % (self.typename, int (length), int (capacity))) 496 else: 497 return ('%s of length %d, capacity %d' 498 % (self.typename, int (finish - start), int (end - start))) 499 500 def display_hint(self): 501 return 'array' 502 503class StdVectorIteratorPrinter: 504 "Print std::vector::iterator" 505 506 def __init__(self, typename, val): 507 self.val = val 508 509 def to_string(self): 510 if not self.val['_M_current']: 511 return 'non-dereferenceable iterator for std::vector' 512 return str(self.val['_M_current'].dereference()) 513 514# TODO add printer for vector<bool>'s _Bit_iterator and _Bit_const_iterator 515 516class StdTuplePrinter: 517 "Print a std::tuple" 518 519 class _iterator(Iterator): 520 @staticmethod 521 def _is_nonempty_tuple (nodes): 522 if len (nodes) == 2: 523 if is_specialization_of (nodes[1].type, '__tuple_base'): 524 return True 525 elif len (nodes) == 1: 526 return True 527 elif len (nodes) == 0: 528 return False 529 raise ValueError("Top of tuple tree does not consist of a single node.") 530 531 def __init__ (self, head): 532 self.head = head 533 534 # Set the base class as the initial head of the 535 # tuple. 536 nodes = self.head.type.fields () 537 if self._is_nonempty_tuple (nodes): 538 # Set the actual head to the first pair. 539 self.head = self.head.cast (nodes[0].type) 540 self.count = 0 541 542 def __iter__ (self): 543 return self 544 545 def __next__ (self): 546 # Check for further recursions in the inheritance tree. 547 # For a GCC 5+ tuple self.head is None after visiting all nodes: 548 if not self.head: 549 raise StopIteration 550 nodes = self.head.type.fields () 551 # For a GCC 4.x tuple there is a final node with no fields: 552 if len (nodes) == 0: 553 raise StopIteration 554 # Check that this iteration has an expected structure. 555 if len (nodes) > 2: 556 raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") 557 558 if len (nodes) == 1: 559 # This is the last node of a GCC 5+ std::tuple. 560 impl = self.head.cast (nodes[0].type) 561 self.head = None 562 else: 563 # Either a node before the last node, or the last node of 564 # a GCC 4.x tuple (which has an empty parent). 565 566 # - Left node is the next recursion parent. 567 # - Right node is the actual class contained in the tuple. 568 569 # Process right node. 570 impl = self.head.cast (nodes[1].type) 571 572 # Process left node and set it as head. 573 self.head = self.head.cast (nodes[0].type) 574 575 self.count = self.count + 1 576 577 # Finally, check the implementation. If it is 578 # wrapped in _M_head_impl return that, otherwise return 579 # the value "as is". 580 fields = impl.type.fields () 581 if len (fields) < 1 or fields[0].name != "_M_head_impl": 582 return ('[%d]' % self.count, impl) 583 else: 584 return ('[%d]' % self.count, impl['_M_head_impl']) 585 586 def __init__ (self, typename, val): 587 self.typename = strip_versioned_namespace(typename) 588 self.val = val; 589 590 def children (self): 591 return self._iterator (self.val) 592 593 def to_string (self): 594 if len (self.val.type.fields ()) == 0: 595 return 'empty %s' % (self.typename) 596 return '%s containing' % (self.typename) 597 598class StdStackOrQueuePrinter: 599 "Print a std::stack or std::queue" 600 601 def __init__ (self, typename, val): 602 self.typename = strip_versioned_namespace(typename) 603 self.visualizer = gdb.default_visualizer(val['c']) 604 605 def children (self): 606 return self.visualizer.children() 607 608 def to_string (self): 609 return '%s wrapping: %s' % (self.typename, 610 self.visualizer.to_string()) 611 612 def display_hint (self): 613 if hasattr (self.visualizer, 'display_hint'): 614 return self.visualizer.display_hint () 615 return None 616 617class RbtreeIterator(Iterator): 618 """ 619 Turn an RB-tree-based container (std::map, std::set etc.) into 620 a Python iterable object. 621 """ 622 623 def __init__(self, rbtree): 624 self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] 625 self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] 626 self.count = 0 627 628 def __iter__(self): 629 return self 630 631 def __len__(self): 632 return int (self.size) 633 634 def __next__(self): 635 if self.count == self.size: 636 raise StopIteration 637 result = self.node 638 self.count = self.count + 1 639 if self.count < self.size: 640 # Compute the next node. 641 node = self.node 642 if node.dereference()['_M_right']: 643 node = node.dereference()['_M_right'] 644 while node.dereference()['_M_left']: 645 node = node.dereference()['_M_left'] 646 else: 647 parent = node.dereference()['_M_parent'] 648 while node == parent.dereference()['_M_right']: 649 node = parent 650 parent = parent.dereference()['_M_parent'] 651 if node.dereference()['_M_right'] != parent: 652 node = parent 653 self.node = node 654 return result 655 656def get_value_from_Rb_tree_node(node): 657 """Returns the value held in an _Rb_tree_node<_Val>""" 658 try: 659 member = node.type.fields()[1].name 660 if member == '_M_value_field': 661 # C++03 implementation, node contains the value as a member 662 return node['_M_value_field'] 663 elif member == '_M_storage': 664 # C++11 implementation, node stores value in __aligned_membuf 665 valtype = node.type.template_argument(0) 666 return get_value_from_aligned_membuf(node['_M_storage'], valtype) 667 except: 668 pass 669 raise ValueError("Unsupported implementation for %s" % str(node.type)) 670 671# This is a pretty printer for std::_Rb_tree_iterator (which is 672# std::map::iterator), and has nothing to do with the RbtreeIterator 673# class above. 674class StdRbtreeIteratorPrinter: 675 "Print std::map::iterator, std::set::iterator, etc." 676 677 def __init__ (self, typename, val): 678 self.val = val 679 nodetype = lookup_node_type('_Rb_tree_node', self.val.type) 680 self.link_type = nodetype.pointer() 681 682 def to_string (self): 683 if not self.val['_M_node']: 684 return 'non-dereferenceable iterator for associative container' 685 node = self.val['_M_node'].cast(self.link_type).dereference() 686 return str(get_value_from_Rb_tree_node(node)) 687 688class StdDebugIteratorPrinter: 689 "Print a debug enabled version of an iterator" 690 691 def __init__ (self, typename, val): 692 self.val = val 693 694 # Just strip away the encapsulating __gnu_debug::_Safe_iterator 695 # and return the wrapped iterator value. 696 def to_string (self): 697 base_type = gdb.lookup_type('__gnu_debug::_Safe_iterator_base') 698 itype = self.val.type.template_argument(0) 699 safe_seq = self.val.cast(base_type)['_M_sequence'] 700 if not safe_seq: 701 return str(self.val.cast(itype)) 702 if self.val['_M_version'] != safe_seq['_M_version']: 703 return "invalid iterator" 704 return str(self.val.cast(itype)) 705 706def num_elements(num): 707 """Return either "1 element" or "N elements" depending on the argument.""" 708 return '1 element' if num == 1 else '%d elements' % num 709 710class StdMapPrinter: 711 "Print a std::map or std::multimap" 712 713 # Turn an RbtreeIterator into a pretty-print iterator. 714 class _iter(Iterator): 715 def __init__(self, rbiter, type): 716 self.rbiter = rbiter 717 self.count = 0 718 self.type = type 719 720 def __iter__(self): 721 return self 722 723 def __next__(self): 724 if self.count % 2 == 0: 725 n = next(self.rbiter) 726 n = n.cast(self.type).dereference() 727 n = get_value_from_Rb_tree_node(n) 728 self.pair = n 729 item = n['first'] 730 else: 731 item = self.pair['second'] 732 result = ('[%d]' % self.count, item) 733 self.count = self.count + 1 734 return result 735 736 def __init__ (self, typename, val): 737 self.typename = strip_versioned_namespace(typename) 738 self.val = val 739 740 def to_string (self): 741 return '%s with %s' % (self.typename, 742 num_elements(len(RbtreeIterator (self.val)))) 743 744 def children (self): 745 node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() 746 return self._iter (RbtreeIterator (self.val), node) 747 748 def display_hint (self): 749 return 'map' 750 751class StdSetPrinter: 752 "Print a std::set or std::multiset" 753 754 # Turn an RbtreeIterator into a pretty-print iterator. 755 class _iter(Iterator): 756 def __init__(self, rbiter, type): 757 self.rbiter = rbiter 758 self.count = 0 759 self.type = type 760 761 def __iter__(self): 762 return self 763 764 def __next__(self): 765 item = next(self.rbiter) 766 item = item.cast(self.type).dereference() 767 item = get_value_from_Rb_tree_node(item) 768 # FIXME: this is weird ... what to do? 769 # Maybe a 'set' display hint? 770 result = ('[%d]' % self.count, item) 771 self.count = self.count + 1 772 return result 773 774 def __init__ (self, typename, val): 775 self.typename = strip_versioned_namespace(typename) 776 self.val = val 777 778 def to_string (self): 779 return '%s with %s' % (self.typename, 780 num_elements(len(RbtreeIterator (self.val)))) 781 782 def children (self): 783 node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() 784 return self._iter (RbtreeIterator (self.val), node) 785 786class StdBitsetPrinter: 787 "Print a std::bitset" 788 789 def __init__(self, typename, val): 790 self.typename = strip_versioned_namespace(typename) 791 self.val = val 792 793 def to_string (self): 794 # If template_argument handled values, we could print the 795 # size. Or we could use a regexp on the type. 796 return '%s' % (self.typename) 797 798 def children (self): 799 try: 800 # An empty bitset may not have any members which will 801 # result in an exception being thrown. 802 words = self.val['_M_w'] 803 except: 804 return [] 805 806 wtype = words.type 807 808 # The _M_w member can be either an unsigned long, or an 809 # array. This depends on the template specialization used. 810 # If it is a single long, convert to a single element list. 811 if wtype.code == gdb.TYPE_CODE_ARRAY: 812 tsize = wtype.target ().sizeof 813 else: 814 words = [words] 815 tsize = wtype.sizeof 816 817 nwords = wtype.sizeof / tsize 818 result = [] 819 byte = 0 820 while byte < nwords: 821 w = words[byte] 822 bit = 0 823 while w != 0: 824 if (w & 1) != 0: 825 # Another spot where we could use 'set'? 826 result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) 827 bit = bit + 1 828 w = w >> 1 829 byte = byte + 1 830 return result 831 832class StdDequePrinter: 833 "Print a std::deque" 834 835 class _iter(Iterator): 836 def __init__(self, node, start, end, last, buffer_size): 837 self.node = node 838 self.p = start 839 self.end = end 840 self.last = last 841 self.buffer_size = buffer_size 842 self.count = 0 843 844 def __iter__(self): 845 return self 846 847 def __next__(self): 848 if self.p == self.last: 849 raise StopIteration 850 851 result = ('[%d]' % self.count, self.p.dereference()) 852 self.count = self.count + 1 853 854 # Advance the 'cur' pointer. 855 self.p = self.p + 1 856 if self.p == self.end: 857 # If we got to the end of this bucket, move to the 858 # next bucket. 859 self.node = self.node + 1 860 self.p = self.node[0] 861 self.end = self.p + self.buffer_size 862 863 return result 864 865 def __init__(self, typename, val): 866 self.typename = strip_versioned_namespace(typename) 867 self.val = val 868 self.elttype = val.type.template_argument(0) 869 size = self.elttype.sizeof 870 if size < 512: 871 self.buffer_size = int (512 / size) 872 else: 873 self.buffer_size = 1 874 875 def to_string(self): 876 start = self.val['_M_impl']['_M_start'] 877 end = self.val['_M_impl']['_M_finish'] 878 879 delta_n = end['_M_node'] - start['_M_node'] - 1 880 delta_s = start['_M_last'] - start['_M_cur'] 881 delta_e = end['_M_cur'] - end['_M_first'] 882 883 size = self.buffer_size * delta_n + delta_s + delta_e 884 885 return '%s with %s' % (self.typename, num_elements(long(size))) 886 887 def children(self): 888 start = self.val['_M_impl']['_M_start'] 889 end = self.val['_M_impl']['_M_finish'] 890 return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], 891 end['_M_cur'], self.buffer_size) 892 893 def display_hint (self): 894 return 'array' 895 896class StdDequeIteratorPrinter: 897 "Print std::deque::iterator" 898 899 def __init__(self, typename, val): 900 self.val = val 901 902 def to_string(self): 903 if not self.val['_M_cur']: 904 return 'non-dereferenceable iterator for std::deque' 905 return str(self.val['_M_cur'].dereference()) 906 907class StdStringPrinter: 908 "Print a std::basic_string of some kind" 909 910 def __init__(self, typename, val): 911 self.val = val 912 self.new_string = typename.find("::__cxx11::basic_string") != -1 913 914 def to_string(self): 915 # Make sure &string works, too. 916 type = self.val.type 917 if type.code == gdb.TYPE_CODE_REF: 918 type = type.target () 919 920 # Calculate the length of the string so that to_string returns 921 # the string according to length, not according to first null 922 # encountered. 923 ptr = self.val ['_M_dataplus']['_M_p'] 924 if self.new_string: 925 length = self.val['_M_string_length'] 926 # https://sourceware.org/bugzilla/show_bug.cgi?id=17728 927 ptr = ptr.cast(ptr.type.strip_typedefs()) 928 else: 929 realtype = type.unqualified ().strip_typedefs () 930 reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () 931 header = ptr.cast(reptype) - 1 932 length = header.dereference ()['_M_length'] 933 if hasattr(ptr, "lazy_string"): 934 return ptr.lazy_string (length = length) 935 return ptr.string (length = length) 936 937 def display_hint (self): 938 return 'string' 939 940class Tr1HashtableIterator(Iterator): 941 def __init__ (self, hashtable): 942 self.buckets = hashtable['_M_buckets'] 943 self.bucket = 0 944 self.bucket_count = hashtable['_M_bucket_count'] 945 self.node_type = find_type(hashtable.type, '_Node').pointer() 946 self.node = 0 947 while self.bucket != self.bucket_count: 948 self.node = self.buckets[self.bucket] 949 if self.node: 950 break 951 self.bucket = self.bucket + 1 952 953 def __iter__ (self): 954 return self 955 956 def __next__ (self): 957 if self.node == 0: 958 raise StopIteration 959 node = self.node.cast(self.node_type) 960 result = node.dereference()['_M_v'] 961 self.node = node.dereference()['_M_next']; 962 if self.node == 0: 963 self.bucket = self.bucket + 1 964 while self.bucket != self.bucket_count: 965 self.node = self.buckets[self.bucket] 966 if self.node: 967 break 968 self.bucket = self.bucket + 1 969 return result 970 971class StdHashtableIterator(Iterator): 972 def __init__(self, hashtable): 973 self.node = hashtable['_M_before_begin']['_M_nxt'] 974 valtype = hashtable.type.template_argument(1) 975 cached = hashtable.type.template_argument(9).template_argument(0) 976 node_type = lookup_templ_spec('std::__detail::_Hash_node', str(valtype), 977 'true' if cached else 'false') 978 self.node_type = node_type.pointer() 979 980 def __iter__(self): 981 return self 982 983 def __next__(self): 984 if self.node == 0: 985 raise StopIteration 986 elt = self.node.cast(self.node_type).dereference() 987 self.node = elt['_M_nxt'] 988 valptr = elt['_M_storage'].address 989 valptr = valptr.cast(elt.type.template_argument(0).pointer()) 990 return valptr.dereference() 991 992class Tr1UnorderedSetPrinter: 993 "Print a std::unordered_set or tr1::unordered_set" 994 995 def __init__ (self, typename, val): 996 self.typename = strip_versioned_namespace(typename) 997 self.val = val 998 999 def hashtable (self): 1000 if self.typename.startswith('std::tr1'): 1001 return self.val 1002 return self.val['_M_h'] 1003 1004 def to_string (self): 1005 count = self.hashtable()['_M_element_count'] 1006 return '%s with %s' % (self.typename, num_elements(count)) 1007 1008 @staticmethod 1009 def format_count (i): 1010 return '[%d]' % i 1011 1012 def children (self): 1013 counter = imap (self.format_count, itertools.count()) 1014 if self.typename.startswith('std::tr1'): 1015 return izip (counter, Tr1HashtableIterator (self.hashtable())) 1016 return izip (counter, StdHashtableIterator (self.hashtable())) 1017 1018class Tr1UnorderedMapPrinter: 1019 "Print a std::unordered_map or tr1::unordered_map" 1020 1021 def __init__ (self, typename, val): 1022 self.typename = strip_versioned_namespace(typename) 1023 self.val = val 1024 1025 def hashtable (self): 1026 if self.typename.startswith('std::tr1'): 1027 return self.val 1028 return self.val['_M_h'] 1029 1030 def to_string (self): 1031 count = self.hashtable()['_M_element_count'] 1032 return '%s with %s' % (self.typename, num_elements(count)) 1033 1034 @staticmethod 1035 def flatten (list): 1036 for elt in list: 1037 for i in elt: 1038 yield i 1039 1040 @staticmethod 1041 def format_one (elt): 1042 return (elt['first'], elt['second']) 1043 1044 @staticmethod 1045 def format_count (i): 1046 return '[%d]' % i 1047 1048 def children (self): 1049 counter = imap (self.format_count, itertools.count()) 1050 # Map over the hash table and flatten the result. 1051 if self.typename.startswith('std::tr1'): 1052 data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) 1053 # Zip the two iterators together. 1054 return izip (counter, data) 1055 data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable()))) 1056 # Zip the two iterators together. 1057 return izip (counter, data) 1058 1059 def display_hint (self): 1060 return 'map' 1061 1062class StdForwardListPrinter: 1063 "Print a std::forward_list" 1064 1065 class _iterator(Iterator): 1066 def __init__(self, nodetype, head): 1067 self.nodetype = nodetype 1068 self.base = head['_M_next'] 1069 self.count = 0 1070 1071 def __iter__(self): 1072 return self 1073 1074 def __next__(self): 1075 if self.base == 0: 1076 raise StopIteration 1077 elt = self.base.cast(self.nodetype).dereference() 1078 self.base = elt['_M_next'] 1079 count = self.count 1080 self.count = self.count + 1 1081 valptr = elt['_M_storage'].address 1082 valptr = valptr.cast(elt.type.template_argument(0).pointer()) 1083 return ('[%d]' % count, valptr.dereference()) 1084 1085 def __init__(self, typename, val): 1086 self.val = val 1087 self.typename = strip_versioned_namespace(typename) 1088 1089 def children(self): 1090 nodetype = lookup_node_type('_Fwd_list_node', self.val.type).pointer() 1091 return self._iterator(nodetype, self.val['_M_impl']['_M_head']) 1092 1093 def to_string(self): 1094 if self.val['_M_impl']['_M_head']['_M_next'] == 0: 1095 return 'empty %s' % self.typename 1096 return '%s' % self.typename 1097 1098class SingleObjContainerPrinter(object): 1099 "Base class for printers of containers of single objects" 1100 1101 def __init__ (self, val, viz, hint = None): 1102 self.contained_value = val 1103 self.visualizer = viz 1104 self.hint = hint 1105 1106 def _recognize(self, type): 1107 """Return TYPE as a string after applying type printers""" 1108 global _use_type_printing 1109 if not _use_type_printing: 1110 return str(type) 1111 return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), 1112 type) or str(type) 1113 1114 class _contained(Iterator): 1115 def __init__ (self, val): 1116 self.val = val 1117 1118 def __iter__ (self): 1119 return self 1120 1121 def __next__(self): 1122 if self.val is None: 1123 raise StopIteration 1124 retval = self.val 1125 self.val = None 1126 return ('[contained value]', retval) 1127 1128 def children (self): 1129 if self.contained_value is None: 1130 return self._contained (None) 1131 if hasattr (self.visualizer, 'children'): 1132 return self.visualizer.children () 1133 return self._contained (self.contained_value) 1134 1135 def display_hint (self): 1136 # if contained value is a map we want to display in the same way 1137 if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'): 1138 return self.visualizer.display_hint () 1139 return self.hint 1140 1141def function_pointer_to_name(f): 1142 "Find the name of the function referred to by the gdb.Value f, " 1143 " which should contain a function pointer from the program." 1144 1145 # Turn the function pointer into an actual address. 1146 # This is needed to unpack ppc64 function descriptors. 1147 f = f.dereference().address 1148 1149 if sys.version_info[0] == 2: 1150 # Older versions of GDB need to use long for Python 2, 1151 # because int(f) on 64-bit big-endian values raises a 1152 # gdb.error saying "Cannot convert value to int." 1153 f = long(f) 1154 else: 1155 f = int(f) 1156 1157 try: 1158 # If the function can't be found older versions of GDB raise a 1159 # RuntimeError saying "Cannot locate object file for block." 1160 return gdb.block_for_pc(f).function.name 1161 except: 1162 return None 1163 1164class StdExpAnyPrinter(SingleObjContainerPrinter): 1165 "Print a std::any or std::experimental::any" 1166 1167 def __init__ (self, typename, val): 1168 self.typename = strip_versioned_namespace(typename) 1169 self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', self.typename, 1) 1170 self.val = val 1171 self.contained_type = None 1172 contained_value = None 1173 visualizer = None 1174 mgr = self.val['_M_manager'] 1175 if mgr != 0: 1176 func = function_pointer_to_name(mgr) 1177 if not func: 1178 raise ValueError("Invalid function pointer in %s" % (self.typename)) 1179 rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\((enum )?{0}::_Op, (const {0}|{0} const) ?\*, (union )?{0}::_Arg ?\*\)""".format(typename) 1180 m = re.match(rx, func) 1181 if not m: 1182 raise ValueError("Unknown manager function in %s" % self.typename) 1183 1184 mgrname = m.group(1) 1185 # FIXME need to expand 'std::string' so that gdb.lookup_type works 1186 if 'std::string' in mgrname: 1187 mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1)) 1188 1189 mgrtype = gdb.lookup_type(mgrname) 1190 self.contained_type = mgrtype.template_argument(0) 1191 valptr = None 1192 if '::_Manager_internal' in mgrname: 1193 valptr = self.val['_M_storage']['_M_buffer'].address 1194 elif '::_Manager_external' in mgrname: 1195 valptr = self.val['_M_storage']['_M_ptr'] 1196 else: 1197 raise ValueError("Unknown manager function in %s" % self.typename) 1198 contained_value = valptr.cast(self.contained_type.pointer()).dereference() 1199 visualizer = gdb.default_visualizer(contained_value) 1200 super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer) 1201 1202 def to_string (self): 1203 if self.contained_type is None: 1204 return '%s [no contained value]' % self.typename 1205 desc = "%s containing " % self.typename 1206 if hasattr (self.visualizer, 'children'): 1207 return desc + self.visualizer.to_string () 1208 valtype = self._recognize (self.contained_type) 1209 return desc + strip_versioned_namespace(str(valtype)) 1210 1211class StdExpOptionalPrinter(SingleObjContainerPrinter): 1212 "Print a std::optional or std::experimental::optional" 1213 1214 def __init__ (self, typename, val): 1215 valtype = self._recognize (val.type.template_argument(0)) 1216 typename = strip_versioned_namespace(typename) 1217 self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1) 1218 payload = val['_M_payload'] 1219 if self.typename.startswith('std::experimental'): 1220 engaged = val['_M_engaged'] 1221 contained_value = payload 1222 else: 1223 engaged = payload['_M_engaged'] 1224 contained_value = payload['_M_payload'] 1225 try: 1226 # Since GCC 9 1227 contained_value = contained_value['_M_value'] 1228 except: 1229 pass 1230 visualizer = gdb.default_visualizer (contained_value) 1231 if not engaged: 1232 contained_value = None 1233 super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer) 1234 1235 def to_string (self): 1236 if self.contained_value is None: 1237 return "%s [no contained value]" % self.typename 1238 if hasattr (self.visualizer, 'children'): 1239 return "%s containing %s" % (self.typename, 1240 self.visualizer.to_string()) 1241 return self.typename 1242 1243class StdVariantPrinter(SingleObjContainerPrinter): 1244 "Print a std::variant" 1245 1246 def __init__(self, typename, val): 1247 alternatives = get_template_arg_list(val.type) 1248 self.typename = strip_versioned_namespace(typename) 1249 self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives])) 1250 self.index = val['_M_index'] 1251 if self.index >= len(alternatives): 1252 self.contained_type = None 1253 contained_value = None 1254 visualizer = None 1255 else: 1256 self.contained_type = alternatives[int(self.index)] 1257 addr = val['_M_u']['_M_first']['_M_storage'].address 1258 contained_value = addr.cast(self.contained_type.pointer()).dereference() 1259 visualizer = gdb.default_visualizer(contained_value) 1260 super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array') 1261 1262 def to_string(self): 1263 if self.contained_value is None: 1264 return "%s [no contained value]" % self.typename 1265 if hasattr(self.visualizer, 'children'): 1266 return "%s [index %d] containing %s" % (self.typename, self.index, 1267 self.visualizer.to_string()) 1268 return "%s [index %d]" % (self.typename, self.index) 1269 1270class StdNodeHandlePrinter(SingleObjContainerPrinter): 1271 "Print a container node handle" 1272 1273 def __init__(self, typename, val): 1274 self.value_type = val.type.template_argument(1) 1275 nodetype = val.type.template_argument(2).template_argument(0) 1276 self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node') 1277 self.is_map_node = val.type.template_argument(0) != self.value_type 1278 nodeptr = val['_M_ptr'] 1279 if nodeptr: 1280 if self.is_rb_tree_node: 1281 contained_value = get_value_from_Rb_tree_node(nodeptr.dereference()) 1282 else: 1283 contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'], 1284 self.value_type) 1285 visualizer = gdb.default_visualizer(contained_value) 1286 else: 1287 contained_value = None 1288 visualizer = None 1289 optalloc = val['_M_alloc'] 1290 self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None 1291 super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer, 1292 'array') 1293 1294 def to_string(self): 1295 desc = 'node handle for ' 1296 if not self.is_rb_tree_node: 1297 desc += 'unordered ' 1298 if self.is_map_node: 1299 desc += 'map'; 1300 else: 1301 desc += 'set'; 1302 1303 if self.contained_value: 1304 desc += ' with element' 1305 if hasattr(self.visualizer, 'children'): 1306 return "%s = %s" % (desc, self.visualizer.to_string()) 1307 return desc 1308 else: 1309 return 'empty %s' % desc 1310 1311class StdExpStringViewPrinter: 1312 "Print a std::basic_string_view or std::experimental::basic_string_view" 1313 1314 def __init__ (self, typename, val): 1315 self.val = val 1316 1317 def to_string (self): 1318 ptr = self.val['_M_str'] 1319 len = self.val['_M_len'] 1320 if hasattr (ptr, "lazy_string"): 1321 return ptr.lazy_string (length = len) 1322 return ptr.string (length = len) 1323 1324 def display_hint (self): 1325 return 'string' 1326 1327class StdExpPathPrinter: 1328 "Print a std::experimental::filesystem::path" 1329 1330 def __init__ (self, typename, val): 1331 self.val = val 1332 self.typename = typename 1333 start = self.val['_M_cmpts']['_M_impl']['_M_start'] 1334 finish = self.val['_M_cmpts']['_M_impl']['_M_finish'] 1335 self.num_cmpts = int (finish - start) 1336 1337 def _path_type(self): 1338 t = str(self.val['_M_type']) 1339 if t[-9:] == '_Root_dir': 1340 return "root-directory" 1341 if t[-10:] == '_Root_name': 1342 return "root-name" 1343 return None 1344 1345 def to_string (self): 1346 path = "%s" % self.val ['_M_pathname'] 1347 if self.num_cmpts == 0: 1348 t = self._path_type() 1349 if t: 1350 path = '%s [%s]' % (path, t) 1351 return "experimental::filesystem::path %s" % path 1352 1353 class _iterator(Iterator): 1354 def __init__(self, cmpts, pathtype): 1355 self.pathtype = pathtype 1356 self.item = cmpts['_M_impl']['_M_start'] 1357 self.finish = cmpts['_M_impl']['_M_finish'] 1358 self.count = 0 1359 1360 def __iter__(self): 1361 return self 1362 1363 def __next__(self): 1364 if self.item == self.finish: 1365 raise StopIteration 1366 item = self.item.dereference() 1367 count = self.count 1368 self.count = self.count + 1 1369 self.item = self.item + 1 1370 path = item['_M_pathname'] 1371 t = StdExpPathPrinter(self.pathtype, item)._path_type() 1372 if not t: 1373 t = count 1374 return ('[%s]' % t, path) 1375 1376 def children(self): 1377 return self._iterator(self.val['_M_cmpts'], self.typename) 1378 1379class StdPathPrinter: 1380 "Print a std::filesystem::path" 1381 1382 def __init__ (self, typename, val): 1383 self.val = val 1384 self.typename = typename 1385 impl = unique_ptr_get(self.val['_M_cmpts']['_M_impl']) 1386 self.type = impl.cast(gdb.lookup_type('uintptr_t')) & 3 1387 if self.type == 0: 1388 self.impl = impl 1389 else: 1390 self.impl = None 1391 1392 def _path_type(self): 1393 t = str(self.type.cast(gdb.lookup_type(self.typename + '::_Type'))) 1394 if t[-9:] == '_Root_dir': 1395 return "root-directory" 1396 if t[-10:] == '_Root_name': 1397 return "root-name" 1398 return None 1399 1400 def to_string (self): 1401 path = "%s" % self.val ['_M_pathname'] 1402 if self.type != 0: 1403 t = self._path_type() 1404 if t: 1405 path = '%s [%s]' % (path, t) 1406 return "filesystem::path %s" % path 1407 1408 class _iterator(Iterator): 1409 def __init__(self, impl, pathtype): 1410 self.pathtype = pathtype 1411 if impl: 1412 # We can't access _Impl::_M_size because _Impl is incomplete 1413 # so cast to int* to access the _M_size member at offset zero, 1414 int_type = gdb.lookup_type('int') 1415 cmpt_type = gdb.lookup_type(pathtype+'::_Cmpt') 1416 char_type = gdb.lookup_type('char') 1417 impl = impl.cast(int_type.pointer()) 1418 size = impl.dereference() 1419 #self.capacity = (impl + 1).dereference() 1420 if hasattr(gdb.Type, 'alignof'): 1421 sizeof_Impl = max(2 * int_type.sizeof, cmpt_type.alignof) 1422 else: 1423 sizeof_Impl = 2 * int_type.sizeof 1424 begin = impl.cast(char_type.pointer()) + sizeof_Impl 1425 self.item = begin.cast(cmpt_type.pointer()) 1426 self.finish = self.item + size 1427 self.count = 0 1428 else: 1429 self.item = None 1430 self.finish = None 1431 1432 def __iter__(self): 1433 return self 1434 1435 def __next__(self): 1436 if self.item == self.finish: 1437 raise StopIteration 1438 item = self.item.dereference() 1439 count = self.count 1440 self.count = self.count + 1 1441 self.item = self.item + 1 1442 path = item['_M_pathname'] 1443 t = StdPathPrinter(self.pathtype, item)._path_type() 1444 if not t: 1445 t = count 1446 return ('[%s]' % t, path) 1447 1448 def children(self): 1449 return self._iterator(self.impl, self.typename) 1450 1451 1452class StdPairPrinter: 1453 "Print a std::pair object, with 'first' and 'second' as children" 1454 1455 def __init__(self, typename, val): 1456 self.val = val 1457 1458 class _iter(Iterator): 1459 "An iterator for std::pair types. Returns 'first' then 'second'." 1460 1461 def __init__(self, val): 1462 self.val = val 1463 self.which = 'first' 1464 1465 def __iter__(self): 1466 return self 1467 1468 def __next__(self): 1469 if self.which is None: 1470 raise StopIteration 1471 which = self.which 1472 if which == 'first': 1473 self.which = 'second' 1474 else: 1475 self.which = None 1476 return (which, self.val[which]) 1477 1478 def children(self): 1479 return self._iter(self.val) 1480 1481 def to_string(self): 1482 return None 1483 1484class StdCmpCatPrinter: 1485 "Print a comparison category object" 1486 1487 def __init__ (self, typename, val): 1488 self.typename = typename[typename.rfind(':')+1:] 1489 self.val = val['_M_value'] 1490 1491 def to_string (self): 1492 if self.typename == 'strong_ordering' and self.val == 0: 1493 name = 'equal' 1494 else: 1495 names = {2:'unordered', -1:'less', 0:'equivalent', 1:'greater'} 1496 name = names[int(self.val)] 1497 return 'std::{}::{}'.format(self.typename, name) 1498 1499class StdErrorCodePrinter: 1500 "Print a std::error_code or std::error_condition" 1501 1502 _errno_categories = None # List of categories that use errno values 1503 1504 def __init__ (self, typename, val): 1505 self.val = val 1506 self.typename = strip_versioned_namespace(typename) 1507 # Do this only once ... 1508 if StdErrorCodePrinter._errno_categories is None: 1509 StdErrorCodePrinter._errno_categories = ['generic'] 1510 try: 1511 import posix 1512 StdErrorCodePrinter._errno_categories.append('system') 1513 except ImportError: 1514 pass 1515 1516 @staticmethod 1517 def _category_name(cat): 1518 "Call the virtual function that overrides std::error_category::name()" 1519 gdb.set_convenience_variable('__cat', cat) 1520 return gdb.parse_and_eval('$__cat->name()').string() 1521 1522 def to_string (self): 1523 value = self.val['_M_value'] 1524 category = self._category_name(self.val['_M_cat']) 1525 strval = str(value) 1526 if value == 0: 1527 default_cats = {'error_code':'system', 'error_condition':'generic'} 1528 unqualified = self.typename.split('::')[-1] 1529 if category == default_cats[unqualified]: 1530 return self.typename + ' = { }' # default-constructed value 1531 if value > 0 and category in StdErrorCodePrinter._errno_categories: 1532 try: 1533 strval = errno.errorcode[int(value)] 1534 except: 1535 pass 1536 return '%s = {"%s": %s}' % (self.typename, category, strval) 1537 1538# A "regular expression" printer which conforms to the 1539# "SubPrettyPrinter" protocol from gdb.printing. 1540class RxPrinter(object): 1541 def __init__(self, name, function): 1542 super(RxPrinter, self).__init__() 1543 self.name = name 1544 self.function = function 1545 self.enabled = True 1546 1547 def invoke(self, value): 1548 if not self.enabled: 1549 return None 1550 1551 if value.type.code == gdb.TYPE_CODE_REF: 1552 if hasattr(gdb.Value,"referenced_value"): 1553 value = value.referenced_value() 1554 1555 return self.function(self.name, value) 1556 1557# A pretty-printer that conforms to the "PrettyPrinter" protocol from 1558# gdb.printing. It can also be used directly as an old-style printer. 1559class Printer(object): 1560 def __init__(self, name): 1561 super(Printer, self).__init__() 1562 self.name = name 1563 self.subprinters = [] 1564 self.lookup = {} 1565 self.enabled = True 1566 self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') 1567 1568 def add(self, name, function): 1569 # A small sanity check. 1570 # FIXME 1571 if not self.compiled_rx.match(name): 1572 raise ValueError('libstdc++ programming error: "%s" does not match' % name) 1573 printer = RxPrinter(name, function) 1574 self.subprinters.append(printer) 1575 self.lookup[name] = printer 1576 1577 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. 1578 def add_version(self, base, name, function): 1579 self.add(base + name, function) 1580 if _versioned_namespace: 1581 vbase = re.sub('^(std|__gnu_cxx)::', r'\g<0>%s' % _versioned_namespace, base) 1582 self.add(vbase + name, function) 1583 1584 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 1585 def add_container(self, base, name, function): 1586 self.add_version(base, name, function) 1587 self.add_version(base + '__cxx1998::', name, function) 1588 1589 @staticmethod 1590 def get_basic_type(type): 1591 # If it points to a reference, get the reference. 1592 if type.code == gdb.TYPE_CODE_REF: 1593 type = type.target () 1594 1595 # Get the unqualified type, stripped of typedefs. 1596 type = type.unqualified ().strip_typedefs () 1597 1598 return type.tag 1599 1600 def __call__(self, val): 1601 typename = self.get_basic_type(val.type) 1602 if not typename: 1603 return None 1604 1605 # All the types we match are template types, so we can use a 1606 # dictionary. 1607 match = self.compiled_rx.match(typename) 1608 if not match: 1609 return None 1610 1611 basename = match.group(1) 1612 1613 if val.type.code == gdb.TYPE_CODE_REF: 1614 if hasattr(gdb.Value,"referenced_value"): 1615 val = val.referenced_value() 1616 1617 if basename in self.lookup: 1618 return self.lookup[basename].invoke(val) 1619 1620 # Cannot find a pretty printer. Return None. 1621 return None 1622 1623libstdcxx_printer = None 1624 1625class TemplateTypePrinter(object): 1626 r""" 1627 A type printer for class templates with default template arguments. 1628 1629 Recognizes specializations of class templates and prints them without 1630 any template arguments that use a default template argument. 1631 Type printers are recursively applied to the template arguments. 1632 1633 e.g. replace "std::vector<T, std::allocator<T> >" with "std::vector<T>". 1634 """ 1635 1636 def __init__(self, name, defargs): 1637 self.name = name 1638 self.defargs = defargs 1639 self.enabled = True 1640 1641 class _recognizer(object): 1642 "The recognizer class for TemplateTypePrinter." 1643 1644 def __init__(self, name, defargs): 1645 self.name = name 1646 self.defargs = defargs 1647 # self.type_obj = None 1648 1649 def recognize(self, type_obj): 1650 """ 1651 If type_obj is a specialization of self.name that uses all the 1652 default template arguments for the class template, then return 1653 a string representation of the type without default arguments. 1654 Otherwise, return None. 1655 """ 1656 1657 if type_obj.tag is None: 1658 return None 1659 1660 if not type_obj.tag.startswith(self.name): 1661 return None 1662 1663 template_args = get_template_arg_list(type_obj) 1664 displayed_args = [] 1665 require_defaulted = False 1666 for n in range(len(template_args)): 1667 # The actual template argument in the type: 1668 targ = template_args[n] 1669 # The default template argument for the class template: 1670 defarg = self.defargs.get(n) 1671 if defarg is not None: 1672 # Substitute other template arguments into the default: 1673 defarg = defarg.format(*template_args) 1674 # Fail to recognize the type (by returning None) 1675 # unless the actual argument is the same as the default. 1676 try: 1677 if targ != gdb.lookup_type(defarg): 1678 return None 1679 except gdb.error: 1680 # Type lookup failed, just use string comparison: 1681 if targ.tag != defarg: 1682 return None 1683 # All subsequent args must have defaults: 1684 require_defaulted = True 1685 elif require_defaulted: 1686 return None 1687 else: 1688 # Recursively apply recognizers to the template argument 1689 # and add it to the arguments that will be displayed: 1690 displayed_args.append(self._recognize_subtype(targ)) 1691 1692 # This assumes no class templates in the nested-name-specifier: 1693 template_name = type_obj.tag[0:type_obj.tag.find('<')] 1694 template_name = strip_inline_namespaces(template_name) 1695 1696 return template_name + '<' + ', '.join(displayed_args) + '>' 1697 1698 def _recognize_subtype(self, type_obj): 1699 """Convert a gdb.Type to a string by applying recognizers, 1700 or if that fails then simply converting to a string.""" 1701 1702 if type_obj.code == gdb.TYPE_CODE_PTR: 1703 return self._recognize_subtype(type_obj.target()) + '*' 1704 if type_obj.code == gdb.TYPE_CODE_ARRAY: 1705 type_str = self._recognize_subtype(type_obj.target()) 1706 if str(type_obj.strip_typedefs()).endswith('[]'): 1707 return type_str + '[]' # array of unknown bound 1708 return "%s[%d]" % (type_str, type_obj.range()[1] + 1) 1709 if type_obj.code == gdb.TYPE_CODE_REF: 1710 return self._recognize_subtype(type_obj.target()) + '&' 1711 if hasattr(gdb, 'TYPE_CODE_RVALUE_REF'): 1712 if type_obj.code == gdb.TYPE_CODE_RVALUE_REF: 1713 return self._recognize_subtype(type_obj.target()) + '&&' 1714 1715 type_str = gdb.types.apply_type_recognizers( 1716 gdb.types.get_type_recognizers(), type_obj) 1717 if type_str: 1718 return type_str 1719 return str(type_obj) 1720 1721 def instantiate(self): 1722 "Return a recognizer object for this type printer." 1723 return self._recognizer(self.name, self.defargs) 1724 1725def add_one_template_type_printer(obj, name, defargs): 1726 r""" 1727 Add a type printer for a class template with default template arguments. 1728 1729 Args: 1730 name (str): The template-name of the class template. 1731 defargs (dict int:string) The default template arguments. 1732 1733 Types in defargs can refer to the Nth template-argument using {N} 1734 (with zero-based indices). 1735 1736 e.g. 'unordered_map' has these defargs: 1737 { 2: 'std::hash<{0}>', 1738 3: 'std::equal_to<{0}>', 1739 4: 'std::allocator<std::pair<const {0}, {1}> >' } 1740 1741 """ 1742 printer = TemplateTypePrinter('std::'+name, defargs) 1743 gdb.types.register_type_printer(obj, printer) 1744 1745 # Add type printer for same type in debug namespace: 1746 printer = TemplateTypePrinter('std::__debug::'+name, defargs) 1747 gdb.types.register_type_printer(obj, printer) 1748 1749 if _versioned_namespace: 1750 # Add second type printer for same type in versioned namespace: 1751 ns = 'std::' + _versioned_namespace 1752 # PR 86112 Cannot use dict comprehension here: 1753 defargs = dict((n, d.replace('std::', ns)) for (n,d) in defargs.items()) 1754 printer = TemplateTypePrinter(ns+name, defargs) 1755 gdb.types.register_type_printer(obj, printer) 1756 1757class FilteringTypePrinter(object): 1758 r""" 1759 A type printer that uses typedef names for common template specializations. 1760 1761 Args: 1762 match (str): The class template to recognize. 1763 name (str): The typedef-name that will be used instead. 1764 1765 Checks if a specialization of the class template 'match' is the same type 1766 as the typedef 'name', and prints it as 'name' instead. 1767 1768 e.g. if an instantiation of std::basic_istream<C, T> is the same type as 1769 std::istream then print it as std::istream. 1770 """ 1771 1772 def __init__(self, match, name): 1773 self.match = match 1774 self.name = name 1775 self.enabled = True 1776 1777 class _recognizer(object): 1778 "The recognizer class for TemplateTypePrinter." 1779 1780 def __init__(self, match, name): 1781 self.match = match 1782 self.name = name 1783 self.type_obj = None 1784 1785 def recognize(self, type_obj): 1786 """ 1787 If type_obj starts with self.match and is the same type as 1788 self.name then return self.name, otherwise None. 1789 """ 1790 if type_obj.tag is None: 1791 return None 1792 1793 if self.type_obj is None: 1794 if not type_obj.tag.startswith(self.match): 1795 # Filter didn't match. 1796 return None 1797 try: 1798 self.type_obj = gdb.lookup_type(self.name).strip_typedefs() 1799 except: 1800 pass 1801 if self.type_obj == type_obj: 1802 return strip_inline_namespaces(self.name) 1803 return None 1804 1805 def instantiate(self): 1806 "Return a recognizer object for this type printer." 1807 return self._recognizer(self.match, self.name) 1808 1809def add_one_type_printer(obj, match, name): 1810 printer = FilteringTypePrinter('std::' + match, 'std::' + name) 1811 gdb.types.register_type_printer(obj, printer) 1812 if _versioned_namespace: 1813 ns = 'std::' + _versioned_namespace 1814 printer = FilteringTypePrinter(ns + match, ns + name) 1815 gdb.types.register_type_printer(obj, printer) 1816 1817def register_type_printers(obj): 1818 global _use_type_printing 1819 1820 if not _use_type_printing: 1821 return 1822 1823 # Add type printers for typedefs std::string, std::wstring etc. 1824 for ch in ('', 'w', 'u8', 'u16', 'u32'): 1825 add_one_type_printer(obj, 'basic_string', ch + 'string') 1826 add_one_type_printer(obj, '__cxx11::basic_string', ch + 'string') 1827 # Typedefs for __cxx11::basic_string used to be in namespace __cxx11: 1828 add_one_type_printer(obj, '__cxx11::basic_string', 1829 '__cxx11::' + ch + 'string') 1830 add_one_type_printer(obj, 'basic_string_view', ch + 'string_view') 1831 1832 # Add type printers for typedefs std::istream, std::wistream etc. 1833 for ch in ('', 'w'): 1834 for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream', 1835 'filebuf', 'ifstream', 'ofstream', 'fstream'): 1836 add_one_type_printer(obj, 'basic_' + x, ch + x) 1837 for x in ('stringbuf', 'istringstream', 'ostringstream', 1838 'stringstream'): 1839 add_one_type_printer(obj, 'basic_' + x, ch + x) 1840 # <sstream> types are in __cxx11 namespace, but typedefs aren't: 1841 add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x) 1842 1843 # Add type printers for typedefs regex, wregex, cmatch, wcmatch etc. 1844 for abi in ('', '__cxx11::'): 1845 for ch in ('', 'w'): 1846 add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex') 1847 for ch in ('c', 's', 'wc', 'ws'): 1848 add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match') 1849 for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'): 1850 add_one_type_printer(obj, abi + x, abi + ch + x) 1851 1852 # Note that we can't have a printer for std::wstreampos, because 1853 # it is the same type as std::streampos. 1854 add_one_type_printer(obj, 'fpos', 'streampos') 1855 1856 # Add type printers for <chrono> typedefs. 1857 for dur in ('nanoseconds', 'microseconds', 'milliseconds', 1858 'seconds', 'minutes', 'hours'): 1859 add_one_type_printer(obj, 'duration', dur) 1860 1861 # Add type printers for <random> typedefs. 1862 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') 1863 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand') 1864 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937') 1865 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64') 1866 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base') 1867 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base') 1868 add_one_type_printer(obj, 'discard_block_engine', 'ranlux24') 1869 add_one_type_printer(obj, 'discard_block_engine', 'ranlux48') 1870 add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b') 1871 1872 # Add type printers for experimental::basic_string_view typedefs. 1873 ns = 'experimental::fundamentals_v1::' 1874 for ch in ('', 'w', 'u8', 'u16', 'u32'): 1875 add_one_type_printer(obj, ns + 'basic_string_view', 1876 ns + ch + 'string_view') 1877 1878 # Do not show defaulted template arguments in class templates. 1879 add_one_template_type_printer(obj, 'unique_ptr', 1880 { 1: 'std::default_delete<{0}>' }) 1881 add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'}) 1882 add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'}) 1883 add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'}) 1884 add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'}) 1885 add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'}) 1886 add_one_template_type_printer(obj, 'map', 1887 { 2: 'std::less<{0}>', 1888 3: 'std::allocator<std::pair<{0} const, {1}>>' }) 1889 add_one_template_type_printer(obj, 'multimap', 1890 { 2: 'std::less<{0}>', 1891 3: 'std::allocator<std::pair<{0} const, {1}>>' }) 1892 add_one_template_type_printer(obj, 'set', 1893 { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' }) 1894 add_one_template_type_printer(obj, 'multiset', 1895 { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' }) 1896 add_one_template_type_printer(obj, 'unordered_map', 1897 { 2: 'std::hash<{0}>', 1898 3: 'std::equal_to<{0}>', 1899 4: 'std::allocator<std::pair<{0} const, {1}>>'}) 1900 add_one_template_type_printer(obj, 'unordered_multimap', 1901 { 2: 'std::hash<{0}>', 1902 3: 'std::equal_to<{0}>', 1903 4: 'std::allocator<std::pair<{0} const, {1}>>'}) 1904 add_one_template_type_printer(obj, 'unordered_set', 1905 { 1: 'std::hash<{0}>', 1906 2: 'std::equal_to<{0}>', 1907 3: 'std::allocator<{0}>'}) 1908 add_one_template_type_printer(obj, 'unordered_multiset', 1909 { 1: 'std::hash<{0}>', 1910 2: 'std::equal_to<{0}>', 1911 3: 'std::allocator<{0}>'}) 1912 1913def register_libstdcxx_printers (obj): 1914 "Register libstdc++ pretty-printers with objfile Obj." 1915 1916 global _use_gdb_pp 1917 global libstdcxx_printer 1918 1919 if _use_gdb_pp: 1920 gdb.printing.register_pretty_printer(obj, libstdcxx_printer) 1921 else: 1922 if obj is None: 1923 obj = gdb 1924 obj.pretty_printers.append(libstdcxx_printer) 1925 1926 register_type_printers(obj) 1927 1928def build_libstdcxx_dictionary (): 1929 global libstdcxx_printer 1930 1931 libstdcxx_printer = Printer("libstdc++-v6") 1932 1933 # libstdc++ objects requiring pretty-printing. 1934 # In order from: 1935 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html 1936 libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) 1937 libstdcxx_printer.add_version('std::__cxx11::', 'basic_string', StdStringPrinter) 1938 libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) 1939 libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) 1940 libstdcxx_printer.add_version('std::', 'error_code', StdErrorCodePrinter) 1941 libstdcxx_printer.add_version('std::', 'error_condition', StdErrorCodePrinter) 1942 libstdcxx_printer.add_container('std::', 'list', StdListPrinter) 1943 libstdcxx_printer.add_container('std::__cxx11::', 'list', StdListPrinter) 1944 libstdcxx_printer.add_container('std::', 'map', StdMapPrinter) 1945 libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter) 1946 libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter) 1947 libstdcxx_printer.add_version('std::', 'pair', StdPairPrinter) 1948 libstdcxx_printer.add_version('std::', 'priority_queue', 1949 StdStackOrQueuePrinter) 1950 libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter) 1951 libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter) 1952 libstdcxx_printer.add_container('std::', 'set', StdSetPrinter) 1953 libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter) 1954 libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) 1955 libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) 1956 # vector<bool> 1957 1958 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. 1959 libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) 1960 libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) 1961 libstdcxx_printer.add('std::__debug::list', StdListPrinter) 1962 libstdcxx_printer.add('std::__debug::map', StdMapPrinter) 1963 libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) 1964 libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) 1965 libstdcxx_printer.add('std::__debug::priority_queue', 1966 StdStackOrQueuePrinter) 1967 libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) 1968 libstdcxx_printer.add('std::__debug::set', StdSetPrinter) 1969 libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) 1970 libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) 1971 libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) 1972 1973 # These are the TR1 and C++11 printers. 1974 # For array - the default GDB pretty-printer seems reasonable. 1975 libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter) 1976 libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter) 1977 libstdcxx_printer.add_container('std::', 'unordered_map', 1978 Tr1UnorderedMapPrinter) 1979 libstdcxx_printer.add_container('std::', 'unordered_set', 1980 Tr1UnorderedSetPrinter) 1981 libstdcxx_printer.add_container('std::', 'unordered_multimap', 1982 Tr1UnorderedMapPrinter) 1983 libstdcxx_printer.add_container('std::', 'unordered_multiset', 1984 Tr1UnorderedSetPrinter) 1985 libstdcxx_printer.add_container('std::', 'forward_list', 1986 StdForwardListPrinter) 1987 1988 libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) 1989 libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) 1990 libstdcxx_printer.add_version('std::tr1::', 'unordered_map', 1991 Tr1UnorderedMapPrinter) 1992 libstdcxx_printer.add_version('std::tr1::', 'unordered_set', 1993 Tr1UnorderedSetPrinter) 1994 libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap', 1995 Tr1UnorderedMapPrinter) 1996 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', 1997 Tr1UnorderedSetPrinter) 1998 1999 # These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases. 2000 # The tr1 namespace containers do not have any debug equivalents, 2001 # so do not register printers for them. 2002 libstdcxx_printer.add('std::__debug::unordered_map', 2003 Tr1UnorderedMapPrinter) 2004 libstdcxx_printer.add('std::__debug::unordered_set', 2005 Tr1UnorderedSetPrinter) 2006 libstdcxx_printer.add('std::__debug::unordered_multimap', 2007 Tr1UnorderedMapPrinter) 2008 libstdcxx_printer.add('std::__debug::unordered_multiset', 2009 Tr1UnorderedSetPrinter) 2010 libstdcxx_printer.add('std::__debug::forward_list', 2011 StdForwardListPrinter) 2012 2013 # Library Fundamentals TS components 2014 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 2015 'any', StdExpAnyPrinter) 2016 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 2017 'optional', StdExpOptionalPrinter) 2018 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 2019 'basic_string_view', StdExpStringViewPrinter) 2020 # Filesystem TS components 2021 libstdcxx_printer.add_version('std::experimental::filesystem::v1::', 2022 'path', StdExpPathPrinter) 2023 libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::', 2024 'path', StdExpPathPrinter) 2025 libstdcxx_printer.add_version('std::filesystem::', 2026 'path', StdPathPrinter) 2027 libstdcxx_printer.add_version('std::filesystem::__cxx11::', 2028 'path', StdPathPrinter) 2029 2030 # C++17 components 2031 libstdcxx_printer.add_version('std::', 2032 'any', StdExpAnyPrinter) 2033 libstdcxx_printer.add_version('std::', 2034 'optional', StdExpOptionalPrinter) 2035 libstdcxx_printer.add_version('std::', 2036 'basic_string_view', StdExpStringViewPrinter) 2037 libstdcxx_printer.add_version('std::', 2038 'variant', StdVariantPrinter) 2039 libstdcxx_printer.add_version('std::', 2040 '_Node_handle', StdNodeHandlePrinter) 2041 2042 # C++20 components 2043 libstdcxx_printer.add_version('std::', 'partial_ordering', StdCmpCatPrinter) 2044 libstdcxx_printer.add_version('std::', 'weak_ordering', StdCmpCatPrinter) 2045 libstdcxx_printer.add_version('std::', 'strong_ordering', StdCmpCatPrinter) 2046 2047 # Extensions. 2048 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) 2049 2050 if True: 2051 # These shouldn't be necessary, if GDB "print *i" worked. 2052 # But it often doesn't, so here they are. 2053 libstdcxx_printer.add_container('std::', '_List_iterator', 2054 StdListIteratorPrinter) 2055 libstdcxx_printer.add_container('std::', '_List_const_iterator', 2056 StdListIteratorPrinter) 2057 libstdcxx_printer.add_version('std::', '_Rb_tree_iterator', 2058 StdRbtreeIteratorPrinter) 2059 libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator', 2060 StdRbtreeIteratorPrinter) 2061 libstdcxx_printer.add_container('std::', '_Deque_iterator', 2062 StdDequeIteratorPrinter) 2063 libstdcxx_printer.add_container('std::', '_Deque_const_iterator', 2064 StdDequeIteratorPrinter) 2065 libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', 2066 StdVectorIteratorPrinter) 2067 libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', 2068 StdSlistIteratorPrinter) 2069 libstdcxx_printer.add_container('std::', '_Fwd_list_iterator', 2070 StdFwdListIteratorPrinter) 2071 libstdcxx_printer.add_container('std::', '_Fwd_list_const_iterator', 2072 StdFwdListIteratorPrinter) 2073 2074 # Debug (compiled with -D_GLIBCXX_DEBUG) printer 2075 # registrations. 2076 libstdcxx_printer.add('__gnu_debug::_Safe_iterator', 2077 StdDebugIteratorPrinter) 2078 2079build_libstdcxx_dictionary () 2080