1# Pretty-printers for libstdc++. 2 3# Copyright (C) 2008-2016 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 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 # Strip cv-qualifiers. PR 67440. 89 search = '%s::%s' % (typ.unqualified(), 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 field = typ.fields()[0] 98 if not field.is_base_class: 99 raise ValueError("Cannot find type %s::%s" % (str(orig), name)) 100 typ = field.type 101 102class SharedPointerPrinter: 103 "Print a shared_ptr or weak_ptr" 104 105 def __init__ (self, typename, val): 106 self.typename = typename 107 self.val = val 108 109 def to_string (self): 110 state = 'empty' 111 refcounts = self.val['_M_refcount']['_M_pi'] 112 if refcounts != 0: 113 usecount = refcounts['_M_use_count'] 114 weakcount = refcounts['_M_weak_count'] 115 if usecount == 0: 116 state = 'expired, weak %d' % weakcount 117 else: 118 state = 'count %d, weak %d' % (usecount, weakcount - 1) 119 return '%s (%s) %s' % (self.typename, state, self.val['_M_ptr']) 120 121class UniquePointerPrinter: 122 "Print a unique_ptr" 123 124 def __init__ (self, typename, val): 125 self.val = val 126 127 def to_string (self): 128 v = self.val['_M_t']['_M_head_impl'] 129 return 'std::unique_ptr<%s> containing %s' % (str(v.type.target()), 130 str(v)) 131 132def get_value_from_list_node(node): 133 """Returns the value held in an _List_node<_Val>""" 134 try: 135 member = node.type.fields()[1].name 136 if member == '_M_data': 137 # C++03 implementation, node contains the value as a member 138 return node['_M_data'] 139 elif member == '_M_storage': 140 # C++11 implementation, node stores value in __aligned_membuf 141 p = node['_M_storage']['_M_storage'].address 142 p = p.cast(node.type.template_argument(0).pointer()) 143 return p.dereference() 144 except: 145 pass 146 raise ValueError("Unsupported implementation for %s" % str(node.type)) 147 148class StdListPrinter: 149 "Print a std::list" 150 151 class _iterator(Iterator): 152 def __init__(self, nodetype, head): 153 self.nodetype = nodetype 154 self.base = head['_M_next'] 155 self.head = head.address 156 self.count = 0 157 158 def __iter__(self): 159 return self 160 161 def __next__(self): 162 if self.base == self.head: 163 raise StopIteration 164 elt = self.base.cast(self.nodetype).dereference() 165 self.base = elt['_M_next'] 166 count = self.count 167 self.count = self.count + 1 168 val = get_value_from_list_node(elt) 169 return ('[%d]' % count, val) 170 171 def __init__(self, typename, val): 172 self.typename = typename 173 self.val = val 174 175 def children(self): 176 nodetype = find_type(self.val.type, '_Node') 177 nodetype = nodetype.strip_typedefs().pointer() 178 return self._iterator(nodetype, self.val['_M_impl']['_M_node']) 179 180 def to_string(self): 181 if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: 182 return 'empty %s' % (self.typename) 183 return '%s' % (self.typename) 184 185class StdListIteratorPrinter: 186 "Print std::list::iterator" 187 188 def __init__(self, typename, val): 189 self.val = val 190 self.typename = typename 191 192 def to_string(self): 193 if not self.val['_M_node']: 194 return 'non-dereferenceable iterator for std::list' 195 nodetype = find_type(self.val.type, '_Node') 196 nodetype = nodetype.strip_typedefs().pointer() 197 node = self.val['_M_node'].cast(nodetype).dereference() 198 return str(get_value_from_list_node(node)) 199 200class StdSlistPrinter: 201 "Print a __gnu_cxx::slist" 202 203 class _iterator(Iterator): 204 def __init__(self, nodetype, head): 205 self.nodetype = nodetype 206 self.base = head['_M_head']['_M_next'] 207 self.count = 0 208 209 def __iter__(self): 210 return self 211 212 def __next__(self): 213 if self.base == 0: 214 raise StopIteration 215 elt = self.base.cast(self.nodetype).dereference() 216 self.base = elt['_M_next'] 217 count = self.count 218 self.count = self.count + 1 219 return ('[%d]' % count, elt['_M_data']) 220 221 def __init__(self, typename, val): 222 self.val = val 223 224 def children(self): 225 nodetype = find_type(self.val.type, '_Node') 226 nodetype = nodetype.strip_typedefs().pointer() 227 return self._iterator(nodetype, self.val) 228 229 def to_string(self): 230 if self.val['_M_head']['_M_next'] == 0: 231 return 'empty __gnu_cxx::slist' 232 return '__gnu_cxx::slist' 233 234class StdSlistIteratorPrinter: 235 "Print __gnu_cxx::slist::iterator" 236 237 def __init__(self, typename, val): 238 self.val = val 239 240 def to_string(self): 241 if not self.val['_M_node']: 242 return 'non-dereferenceable iterator for __gnu_cxx::slist' 243 nodetype = find_type(self.val.type, '_Node') 244 nodetype = nodetype.strip_typedefs().pointer() 245 return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data']) 246 247class StdVectorPrinter: 248 "Print a std::vector" 249 250 class _iterator(Iterator): 251 def __init__ (self, start, finish, bitvec): 252 self.bitvec = bitvec 253 if bitvec: 254 self.item = start['_M_p'] 255 self.so = start['_M_offset'] 256 self.finish = finish['_M_p'] 257 self.fo = finish['_M_offset'] 258 itype = self.item.dereference().type 259 self.isize = 8 * itype.sizeof 260 else: 261 self.item = start 262 self.finish = finish 263 self.count = 0 264 265 def __iter__(self): 266 return self 267 268 def __next__(self): 269 count = self.count 270 self.count = self.count + 1 271 if self.bitvec: 272 if self.item == self.finish and self.so >= self.fo: 273 raise StopIteration 274 elt = self.item.dereference() 275 if elt & (1 << self.so): 276 obit = 1 277 else: 278 obit = 0 279 self.so = self.so + 1 280 if self.so >= self.isize: 281 self.item = self.item + 1 282 self.so = 0 283 return ('[%d]' % count, obit) 284 else: 285 if self.item == self.finish: 286 raise StopIteration 287 elt = self.item.dereference() 288 self.item = self.item + 1 289 return ('[%d]' % count, elt) 290 291 def __init__(self, typename, val): 292 self.typename = typename 293 self.val = val 294 self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL 295 296 def children(self): 297 return self._iterator(self.val['_M_impl']['_M_start'], 298 self.val['_M_impl']['_M_finish'], 299 self.is_bool) 300 301 def to_string(self): 302 start = self.val['_M_impl']['_M_start'] 303 finish = self.val['_M_impl']['_M_finish'] 304 end = self.val['_M_impl']['_M_end_of_storage'] 305 if self.is_bool: 306 start = self.val['_M_impl']['_M_start']['_M_p'] 307 so = self.val['_M_impl']['_M_start']['_M_offset'] 308 finish = self.val['_M_impl']['_M_finish']['_M_p'] 309 fo = self.val['_M_impl']['_M_finish']['_M_offset'] 310 itype = start.dereference().type 311 bl = 8 * itype.sizeof 312 length = (bl - so) + bl * ((finish - start) - 1) + fo 313 capacity = bl * (end - start) 314 return ('%s<bool> of length %d, capacity %d' 315 % (self.typename, int (length), int (capacity))) 316 else: 317 return ('%s of length %d, capacity %d' 318 % (self.typename, int (finish - start), int (end - start))) 319 320 def display_hint(self): 321 return 'array' 322 323class StdVectorIteratorPrinter: 324 "Print std::vector::iterator" 325 326 def __init__(self, typename, val): 327 self.val = val 328 329 def to_string(self): 330 if not self.val['_M_current']: 331 return 'non-dereferenceable iterator for std::vector' 332 return str(self.val['_M_current'].dereference()) 333 334class StdTuplePrinter: 335 "Print a std::tuple" 336 337 class _iterator(Iterator): 338 def __init__ (self, head): 339 self.head = head 340 341 # Set the base class as the initial head of the 342 # tuple. 343 nodes = self.head.type.fields () 344 if len (nodes) == 1: 345 # Set the actual head to the first pair. 346 self.head = self.head.cast (nodes[0].type) 347 elif len (nodes) != 0: 348 raise ValueError("Top of tuple tree does not consist of a single node.") 349 self.count = 0 350 351 def __iter__ (self): 352 return self 353 354 def __next__ (self): 355 # Check for further recursions in the inheritance tree. 356 # For a GCC 5+ tuple self.head is None after visiting all nodes: 357 if not self.head: 358 raise StopIteration 359 nodes = self.head.type.fields () 360 # For a GCC 4.x tuple there is a final node with no fields: 361 if len (nodes) == 0: 362 raise StopIteration 363 # Check that this iteration has an expected structure. 364 if len (nodes) > 2: 365 raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") 366 367 if len (nodes) == 1: 368 # This is the last node of a GCC 5+ std::tuple. 369 impl = self.head.cast (nodes[0].type) 370 self.head = None 371 else: 372 # Either a node before the last node, or the last node of 373 # a GCC 4.x tuple (which has an empty parent). 374 375 # - Left node is the next recursion parent. 376 # - Right node is the actual class contained in the tuple. 377 378 # Process right node. 379 impl = self.head.cast (nodes[1].type) 380 381 # Process left node and set it as head. 382 self.head = self.head.cast (nodes[0].type) 383 384 self.count = self.count + 1 385 386 # Finally, check the implementation. If it is 387 # wrapped in _M_head_impl return that, otherwise return 388 # the value "as is". 389 fields = impl.type.fields () 390 if len (fields) < 1 or fields[0].name != "_M_head_impl": 391 return ('[%d]' % self.count, impl) 392 else: 393 return ('[%d]' % self.count, impl['_M_head_impl']) 394 395 def __init__ (self, typename, val): 396 self.typename = typename 397 self.val = val; 398 399 def children (self): 400 return self._iterator (self.val) 401 402 def to_string (self): 403 if len (self.val.type.fields ()) == 0: 404 return 'empty %s' % (self.typename) 405 return '%s containing' % (self.typename) 406 407class StdStackOrQueuePrinter: 408 "Print a std::stack or std::queue" 409 410 def __init__ (self, typename, val): 411 self.typename = typename 412 self.visualizer = gdb.default_visualizer(val['c']) 413 414 def children (self): 415 return self.visualizer.children() 416 417 def to_string (self): 418 return '%s wrapping: %s' % (self.typename, 419 self.visualizer.to_string()) 420 421 def display_hint (self): 422 if hasattr (self.visualizer, 'display_hint'): 423 return self.visualizer.display_hint () 424 return None 425 426class RbtreeIterator(Iterator): 427 """ 428 Turn an RB-tree-based container (std::map, std::set etc.) into 429 a Python iterable object. 430 """ 431 432 def __init__(self, rbtree): 433 self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] 434 self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] 435 self.count = 0 436 437 def __iter__(self): 438 return self 439 440 def __len__(self): 441 return int (self.size) 442 443 def __next__(self): 444 if self.count == self.size: 445 raise StopIteration 446 result = self.node 447 self.count = self.count + 1 448 if self.count < self.size: 449 # Compute the next node. 450 node = self.node 451 if node.dereference()['_M_right']: 452 node = node.dereference()['_M_right'] 453 while node.dereference()['_M_left']: 454 node = node.dereference()['_M_left'] 455 else: 456 parent = node.dereference()['_M_parent'] 457 while node == parent.dereference()['_M_right']: 458 node = parent 459 parent = parent.dereference()['_M_parent'] 460 if node.dereference()['_M_right'] != parent: 461 node = parent 462 self.node = node 463 return result 464 465def get_value_from_Rb_tree_node(node): 466 """Returns the value held in an _Rb_tree_node<_Val>""" 467 try: 468 member = node.type.fields()[1].name 469 if member == '_M_value_field': 470 # C++03 implementation, node contains the value as a member 471 return node['_M_value_field'] 472 elif member == '_M_storage': 473 # C++11 implementation, node stores value in __aligned_membuf 474 p = node['_M_storage']['_M_storage'].address 475 p = p.cast(node.type.template_argument(0).pointer()) 476 return p.dereference() 477 except: 478 pass 479 raise ValueError("Unsupported implementation for %s" % str(node.type)) 480 481# This is a pretty printer for std::_Rb_tree_iterator (which is 482# std::map::iterator), and has nothing to do with the RbtreeIterator 483# class above. 484class StdRbtreeIteratorPrinter: 485 "Print std::map::iterator, std::set::iterator, etc." 486 487 def __init__ (self, typename, val): 488 self.val = val 489 valtype = self.val.type.template_argument(0).strip_typedefs() 490 nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>') 491 self.link_type = nodetype.strip_typedefs().pointer() 492 493 def to_string (self): 494 if not self.val['_M_node']: 495 return 'non-dereferenceable iterator for associative container' 496 node = self.val['_M_node'].cast(self.link_type).dereference() 497 return str(get_value_from_Rb_tree_node(node)) 498 499class StdDebugIteratorPrinter: 500 "Print a debug enabled version of an iterator" 501 502 def __init__ (self, typename, val): 503 self.val = val 504 505 # Just strip away the encapsulating __gnu_debug::_Safe_iterator 506 # and return the wrapped iterator value. 507 def to_string (self): 508 itype = self.val.type.template_argument(0) 509 return str(self.val.cast(itype)) 510 511class StdMapPrinter: 512 "Print a std::map or std::multimap" 513 514 # Turn an RbtreeIterator into a pretty-print iterator. 515 class _iter(Iterator): 516 def __init__(self, rbiter, type): 517 self.rbiter = rbiter 518 self.count = 0 519 self.type = type 520 521 def __iter__(self): 522 return self 523 524 def __next__(self): 525 if self.count % 2 == 0: 526 n = next(self.rbiter) 527 n = n.cast(self.type).dereference() 528 n = get_value_from_Rb_tree_node(n) 529 self.pair = n 530 item = n['first'] 531 else: 532 item = self.pair['second'] 533 result = ('[%d]' % self.count, item) 534 self.count = self.count + 1 535 return result 536 537 def __init__ (self, typename, val): 538 self.typename = typename 539 self.val = val 540 541 def to_string (self): 542 return '%s with %d elements' % (self.typename, 543 len (RbtreeIterator (self.val))) 544 545 def children (self): 546 rep_type = find_type(self.val.type, '_Rep_type') 547 node = find_type(rep_type, '_Link_type') 548 node = node.strip_typedefs() 549 return self._iter (RbtreeIterator (self.val), node) 550 551 def display_hint (self): 552 return 'map' 553 554class StdSetPrinter: 555 "Print a std::set or std::multiset" 556 557 # Turn an RbtreeIterator into a pretty-print iterator. 558 class _iter(Iterator): 559 def __init__(self, rbiter, type): 560 self.rbiter = rbiter 561 self.count = 0 562 self.type = type 563 564 def __iter__(self): 565 return self 566 567 def __next__(self): 568 item = next(self.rbiter) 569 item = item.cast(self.type).dereference() 570 item = get_value_from_Rb_tree_node(item) 571 # FIXME: this is weird ... what to do? 572 # Maybe a 'set' display hint? 573 result = ('[%d]' % self.count, item) 574 self.count = self.count + 1 575 return result 576 577 def __init__ (self, typename, val): 578 self.typename = typename 579 self.val = val 580 581 def to_string (self): 582 return '%s with %d elements' % (self.typename, 583 len (RbtreeIterator (self.val))) 584 585 def children (self): 586 rep_type = find_type(self.val.type, '_Rep_type') 587 node = find_type(rep_type, '_Link_type') 588 node = node.strip_typedefs() 589 return self._iter (RbtreeIterator (self.val), node) 590 591class StdBitsetPrinter: 592 "Print a std::bitset" 593 594 def __init__(self, typename, val): 595 self.typename = typename 596 self.val = val 597 598 def to_string (self): 599 # If template_argument handled values, we could print the 600 # size. Or we could use a regexp on the type. 601 return '%s' % (self.typename) 602 603 def children (self): 604 words = self.val['_M_w'] 605 wtype = words.type 606 607 # The _M_w member can be either an unsigned long, or an 608 # array. This depends on the template specialization used. 609 # If it is a single long, convert to a single element list. 610 if wtype.code == gdb.TYPE_CODE_ARRAY: 611 tsize = wtype.target ().sizeof 612 else: 613 words = [words] 614 tsize = wtype.sizeof 615 616 nwords = wtype.sizeof / tsize 617 result = [] 618 byte = 0 619 while byte < nwords: 620 w = words[byte] 621 bit = 0 622 while w != 0: 623 if (w & 1) != 0: 624 # Another spot where we could use 'set'? 625 result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) 626 bit = bit + 1 627 w = w >> 1 628 byte = byte + 1 629 return result 630 631class StdDequePrinter: 632 "Print a std::deque" 633 634 class _iter(Iterator): 635 def __init__(self, node, start, end, last, buffer_size): 636 self.node = node 637 self.p = start 638 self.end = end 639 self.last = last 640 self.buffer_size = buffer_size 641 self.count = 0 642 643 def __iter__(self): 644 return self 645 646 def __next__(self): 647 if self.p == self.last: 648 raise StopIteration 649 650 result = ('[%d]' % self.count, self.p.dereference()) 651 self.count = self.count + 1 652 653 # Advance the 'cur' pointer. 654 self.p = self.p + 1 655 if self.p == self.end: 656 # If we got to the end of this bucket, move to the 657 # next bucket. 658 self.node = self.node + 1 659 self.p = self.node[0] 660 self.end = self.p + self.buffer_size 661 662 return result 663 664 def __init__(self, typename, val): 665 self.typename = typename 666 self.val = val 667 self.elttype = val.type.template_argument(0) 668 size = self.elttype.sizeof 669 if size < 512: 670 self.buffer_size = int (512 / size) 671 else: 672 self.buffer_size = 1 673 674 def to_string(self): 675 start = self.val['_M_impl']['_M_start'] 676 end = self.val['_M_impl']['_M_finish'] 677 678 delta_n = end['_M_node'] - start['_M_node'] - 1 679 delta_s = start['_M_last'] - start['_M_cur'] 680 delta_e = end['_M_cur'] - end['_M_first'] 681 682 size = self.buffer_size * delta_n + delta_s + delta_e 683 684 return '%s with %d elements' % (self.typename, long (size)) 685 686 def children(self): 687 start = self.val['_M_impl']['_M_start'] 688 end = self.val['_M_impl']['_M_finish'] 689 return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], 690 end['_M_cur'], self.buffer_size) 691 692 def display_hint (self): 693 return 'array' 694 695class StdDequeIteratorPrinter: 696 "Print std::deque::iterator" 697 698 def __init__(self, typename, val): 699 self.val = val 700 701 def to_string(self): 702 if not self.val['_M_cur']: 703 return 'non-dereferenceable iterator for std::deque' 704 return str(self.val['_M_cur'].dereference()) 705 706class StdStringPrinter: 707 "Print a std::basic_string of some kind" 708 709 def __init__(self, typename, val): 710 self.val = val 711 self.new_string = typename.find("::__cxx11::basic_string") != -1 712 713 def to_string(self): 714 # Make sure &string works, too. 715 type = self.val.type 716 if type.code == gdb.TYPE_CODE_REF: 717 type = type.target () 718 719 # Calculate the length of the string so that to_string returns 720 # the string according to length, not according to first null 721 # encountered. 722 ptr = self.val ['_M_dataplus']['_M_p'] 723 if self.new_string: 724 length = self.val['_M_string_length'] 725 # https://sourceware.org/bugzilla/show_bug.cgi?id=17728 726 ptr = ptr.cast(ptr.type.strip_typedefs()) 727 else: 728 realtype = type.unqualified ().strip_typedefs () 729 reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () 730 header = ptr.cast(reptype) - 1 731 length = header.dereference ()['_M_length'] 732 if hasattr(ptr, "lazy_string"): 733 return ptr.lazy_string (length = length) 734 return ptr.string (length = length) 735 736 def display_hint (self): 737 return 'string' 738 739class Tr1HashtableIterator(Iterator): 740 def __init__ (self, hash): 741 self.buckets = hash['_M_buckets'] 742 self.bucket = 0 743 self.bucket_count = hash['_M_bucket_count'] 744 self.node_type = find_type(hash.type, '_Node').pointer() 745 self.node = 0 746 while self.bucket != self.bucket_count: 747 self.node = self.buckets[self.bucket] 748 if self.node: 749 break 750 self.bucket = self.bucket + 1 751 752 def __iter__ (self): 753 return self 754 755 def __next__ (self): 756 if self.node == 0: 757 raise StopIteration 758 node = self.node.cast(self.node_type) 759 result = node.dereference()['_M_v'] 760 self.node = node.dereference()['_M_next']; 761 if self.node == 0: 762 self.bucket = self.bucket + 1 763 while self.bucket != self.bucket_count: 764 self.node = self.buckets[self.bucket] 765 if self.node: 766 break 767 self.bucket = self.bucket + 1 768 return result 769 770class StdHashtableIterator(Iterator): 771 def __init__(self, hash): 772 self.node = hash['_M_before_begin']['_M_nxt'] 773 self.node_type = find_type(hash.type, '__node_type').pointer() 774 775 def __iter__(self): 776 return self 777 778 def __next__(self): 779 if self.node == 0: 780 raise StopIteration 781 elt = self.node.cast(self.node_type).dereference() 782 self.node = elt['_M_nxt'] 783 valptr = elt['_M_storage'].address 784 valptr = valptr.cast(elt.type.template_argument(0).pointer()) 785 return valptr.dereference() 786 787class Tr1UnorderedSetPrinter: 788 "Print a tr1::unordered_set" 789 790 def __init__ (self, typename, val): 791 self.typename = typename 792 self.val = val 793 794 def hashtable (self): 795 if self.typename.startswith('std::tr1'): 796 return self.val 797 return self.val['_M_h'] 798 799 def to_string (self): 800 return '%s with %d elements' % (self.typename, self.hashtable()['_M_element_count']) 801 802 @staticmethod 803 def format_count (i): 804 return '[%d]' % i 805 806 def children (self): 807 counter = imap (self.format_count, itertools.count()) 808 if self.typename.startswith('std::tr1'): 809 return izip (counter, Tr1HashtableIterator (self.hashtable())) 810 return izip (counter, StdHashtableIterator (self.hashtable())) 811 812class Tr1UnorderedMapPrinter: 813 "Print a tr1::unordered_map" 814 815 def __init__ (self, typename, val): 816 self.typename = typename 817 self.val = val 818 819 def hashtable (self): 820 if self.typename.startswith('std::tr1'): 821 return self.val 822 return self.val['_M_h'] 823 824 def to_string (self): 825 return '%s with %d elements' % (self.typename, self.hashtable()['_M_element_count']) 826 827 @staticmethod 828 def flatten (list): 829 for elt in list: 830 for i in elt: 831 yield i 832 833 @staticmethod 834 def format_one (elt): 835 return (elt['first'], elt['second']) 836 837 @staticmethod 838 def format_count (i): 839 return '[%d]' % i 840 841 def children (self): 842 counter = imap (self.format_count, itertools.count()) 843 # Map over the hash table and flatten the result. 844 if self.typename.startswith('std::tr1'): 845 data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) 846 # Zip the two iterators together. 847 return izip (counter, data) 848 data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable()))) 849 # Zip the two iterators together. 850 return izip (counter, data) 851 852 853 def display_hint (self): 854 return 'map' 855 856class StdForwardListPrinter: 857 "Print a std::forward_list" 858 859 class _iterator(Iterator): 860 def __init__(self, nodetype, head): 861 self.nodetype = nodetype 862 self.base = head['_M_next'] 863 self.count = 0 864 865 def __iter__(self): 866 return self 867 868 def __next__(self): 869 if self.base == 0: 870 raise StopIteration 871 elt = self.base.cast(self.nodetype).dereference() 872 self.base = elt['_M_next'] 873 count = self.count 874 self.count = self.count + 1 875 valptr = elt['_M_storage'].address 876 valptr = valptr.cast(elt.type.template_argument(0).pointer()) 877 return ('[%d]' % count, valptr.dereference()) 878 879 def __init__(self, typename, val): 880 self.val = val 881 self.typename = typename 882 883 def children(self): 884 nodetype = find_type(self.val.type, '_Node') 885 nodetype = nodetype.strip_typedefs().pointer() 886 return self._iterator(nodetype, self.val['_M_impl']['_M_head']) 887 888 def to_string(self): 889 if self.val['_M_impl']['_M_head']['_M_next'] == 0: 890 return 'empty %s' % self.typename 891 return '%s' % self.typename 892 893class SingleObjContainerPrinter(object): 894 "Base class for printers of containers of single objects" 895 896 def __init__ (self, val, viz): 897 self.contained_value = val 898 self.visualizer = viz 899 900 def _recognize(self, type): 901 """Return TYPE as a string after applying type printers""" 902 global _use_type_printing 903 if not _use_type_printing: 904 return str(type) 905 return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), 906 type) or str(type) 907 908 class _contained(Iterator): 909 def __init__ (self, val): 910 self.val = val 911 912 def __iter__ (self): 913 return self 914 915 def __next__(self): 916 if self.val is None: 917 raise StopIteration 918 retval = self.val 919 self.val = None 920 return ('[contained value]', retval) 921 922 def children (self): 923 if self.contained_value is None: 924 return self._contained (None) 925 if hasattr (self.visualizer, 'children'): 926 return self.visualizer.children () 927 return self._contained (self.contained_value) 928 929 def display_hint (self): 930 # if contained value is a map we want to display in the same way 931 if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'): 932 return self.visualizer.display_hint () 933 return None 934 935 936class StdExpAnyPrinter(SingleObjContainerPrinter): 937 "Print a std::experimental::any" 938 939 def __init__ (self, typename, val): 940 self.typename = 'std::experimental::any' 941 self.val = val 942 self.contained_type = None 943 contained_value = None 944 visualizer = None 945 mgr = self.val['_M_manager'] 946 if mgr != 0: 947 func = gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t')))) 948 if not func: 949 raise ValueError("Invalid function pointer in std::experimental::any") 950 rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, {0} const\*, {0}::_Arg\*\)""".format(typename) 951 m = re.match(rx, func.function.name) 952 if not m: 953 raise ValueError("Unknown manager function in std::experimental::any") 954 955 # FIXME need to expand 'std::string' so that gdb.lookup_type works 956 mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1)) 957 mgrtype = gdb.lookup_type(mgrname) 958 self.contained_type = mgrtype.template_argument(0) 959 valptr = None 960 if '::_Manager_internal' in mgrname: 961 valptr = self.val['_M_storage']['_M_buffer'].address 962 elif '::_Manager_external' in mgrname: 963 valptr = self.val['_M_storage']['_M_ptr'] 964 else: 965 raise ValueError("Unknown manager function in std::experimental::any") 966 contained_value = valptr.cast(self.contained_type.pointer()).dereference() 967 visualizer = gdb.default_visualizer(contained_value) 968 super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer) 969 970 def to_string (self): 971 if self.contained_type is None: 972 return '%s [no contained value]' % self.typename 973 desc = "%s containing " % self.typename 974 if hasattr (self.visualizer, 'children'): 975 return desc + self.visualizer.to_string () 976 valtype = self._recognize (self.contained_type) 977 return desc + valtype 978 979class StdExpOptionalPrinter(SingleObjContainerPrinter): 980 "Print a std::experimental::optional" 981 982 def __init__ (self, typename, val): 983 valtype = self._recognize (val.type.template_argument(0)) 984 self.typename = "std::experimental::optional<%s>" % valtype 985 self.val = val 986 contained_value = val['_M_payload'] if self.val['_M_engaged'] else None 987 visualizer = gdb.default_visualizer (val['_M_payload']) 988 super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer) 989 990 def to_string (self): 991 if self.contained_value is None: 992 return "%s [no contained value]" % self.typename 993 if hasattr (self.visualizer, 'children'): 994 return "%s containing %s" % (self.typename, 995 self.visualizer.to_string()) 996 return self.typename 997 998class StdExpStringViewPrinter: 999 "Print a std::experimental::basic_string_view" 1000 1001 def __init__ (self, typename, val): 1002 self.val = val 1003 1004 def to_string (self): 1005 ptr = self.val['_M_str'] 1006 len = self.val['_M_len'] 1007 if hasattr (ptr, "lazy_string"): 1008 return ptr.lazy_string (length = len) 1009 return ptr.string (length = len) 1010 1011 def display_hint (self): 1012 return 'string' 1013 1014class StdExpPathPrinter: 1015 "Print a std::experimental::filesystem::path" 1016 1017 def __init__ (self, typename, val): 1018 self.val = val 1019 start = self.val['_M_cmpts']['_M_impl']['_M_start'] 1020 finish = self.val['_M_cmpts']['_M_impl']['_M_finish'] 1021 self.num_cmpts = int (finish - start) 1022 1023 def _path_type(self): 1024 t = str(self.val['_M_type']) 1025 if t[-9:] == '_Root_dir': 1026 return "root-directory" 1027 if t[-10:] == '_Root_name': 1028 return "root-name" 1029 return None 1030 1031 def to_string (self): 1032 path = "%s" % self.val ['_M_pathname'] 1033 if self.num_cmpts == 0: 1034 t = self._path_type() 1035 if t: 1036 path = '%s [%s]' % (path, t) 1037 return "filesystem::path %s" % path 1038 1039 class _iterator(Iterator): 1040 def __init__(self, cmpts): 1041 self.item = cmpts['_M_impl']['_M_start'] 1042 self.finish = cmpts['_M_impl']['_M_finish'] 1043 self.count = 0 1044 1045 def __iter__(self): 1046 return self 1047 1048 def __next__(self): 1049 if self.item == self.finish: 1050 raise StopIteration 1051 item = self.item.dereference() 1052 count = self.count 1053 self.count = self.count + 1 1054 self.item = self.item + 1 1055 path = item['_M_pathname'] 1056 t = StdExpPathPrinter(item.type.name, item)._path_type() 1057 if not t: 1058 t = count 1059 return ('[%s]' % t, path) 1060 1061 def children(self): 1062 return self._iterator(self.val['_M_cmpts']) 1063 1064 1065class StdPairPrinter: 1066 "Print a std::pair object, with 'first' and 'second' as children" 1067 1068 def __init__(self, typename, val): 1069 self.val = val 1070 1071 class _iter(Iterator): 1072 "An iterator for std::pair types. Returns 'first' then 'second'." 1073 1074 def __init__(self, val): 1075 self.val = val 1076 self.which = 'first' 1077 1078 def __iter__(self): 1079 return self 1080 1081 def __next__(self): 1082 if self.which is None: 1083 raise StopIteration 1084 which = self.which 1085 if which == 'first': 1086 self.which = 'second' 1087 else: 1088 self.which = None 1089 return (which, self.val[which]) 1090 1091 def children(self): 1092 return self._iter(self.val) 1093 1094 def to_string(self): 1095 return None 1096 1097 1098# A "regular expression" printer which conforms to the 1099# "SubPrettyPrinter" protocol from gdb.printing. 1100class RxPrinter(object): 1101 def __init__(self, name, function): 1102 super(RxPrinter, self).__init__() 1103 self.name = name 1104 self.function = function 1105 self.enabled = True 1106 1107 def invoke(self, value): 1108 if not self.enabled: 1109 return None 1110 1111 if value.type.code == gdb.TYPE_CODE_REF: 1112 if hasattr(gdb.Value,"referenced_value"): 1113 value = value.referenced_value() 1114 1115 return self.function(self.name, value) 1116 1117# A pretty-printer that conforms to the "PrettyPrinter" protocol from 1118# gdb.printing. It can also be used directly as an old-style printer. 1119class Printer(object): 1120 def __init__(self, name): 1121 super(Printer, self).__init__() 1122 self.name = name 1123 self.subprinters = [] 1124 self.lookup = {} 1125 self.enabled = True 1126 self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') 1127 1128 def add(self, name, function): 1129 # A small sanity check. 1130 # FIXME 1131 if not self.compiled_rx.match(name): 1132 raise ValueError('libstdc++ programming error: "%s" does not match' % name) 1133 printer = RxPrinter(name, function) 1134 self.subprinters.append(printer) 1135 self.lookup[name] = printer 1136 1137 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. 1138 def add_version(self, base, name, function): 1139 self.add(base + name, function) 1140 self.add(base + '__7::' + name, function) 1141 1142 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 1143 def add_container(self, base, name, function): 1144 self.add_version(base, name, function) 1145 self.add_version(base + '__cxx1998::', name, function) 1146 1147 @staticmethod 1148 def get_basic_type(type): 1149 # If it points to a reference, get the reference. 1150 if type.code == gdb.TYPE_CODE_REF: 1151 type = type.target () 1152 1153 # Get the unqualified type, stripped of typedefs. 1154 type = type.unqualified ().strip_typedefs () 1155 1156 return type.tag 1157 1158 def __call__(self, val): 1159 typename = self.get_basic_type(val.type) 1160 if not typename: 1161 return None 1162 1163 # All the types we match are template types, so we can use a 1164 # dictionary. 1165 match = self.compiled_rx.match(typename) 1166 if not match: 1167 return None 1168 1169 basename = match.group(1) 1170 1171 if val.type.code == gdb.TYPE_CODE_REF: 1172 if hasattr(gdb.Value,"referenced_value"): 1173 val = val.referenced_value() 1174 1175 if basename in self.lookup: 1176 return self.lookup[basename].invoke(val) 1177 1178 # Cannot find a pretty printer. Return None. 1179 return None 1180 1181libstdcxx_printer = None 1182 1183class TemplateTypePrinter(object): 1184 r""" 1185 A type printer for class templates. 1186 1187 Recognizes type names that match a regular expression. 1188 Replaces them with a formatted string which can use replacement field 1189 {N} to refer to the \N subgroup of the regex match. 1190 Type printers are recursively applied to the subgroups. 1191 1192 This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >" 1193 and replacing it with "std::vector<{1}>", omitting the template argument 1194 that uses the default type. 1195 """ 1196 1197 def __init__(self, name, pattern, subst): 1198 self.name = name 1199 self.pattern = re.compile(pattern) 1200 self.subst = subst 1201 self.enabled = True 1202 1203 class _recognizer(object): 1204 def __init__(self, pattern, subst): 1205 self.pattern = pattern 1206 self.subst = subst 1207 self.type_obj = None 1208 1209 def recognize(self, type_obj): 1210 if type_obj.tag is None: 1211 return None 1212 1213 m = self.pattern.match(type_obj.tag) 1214 if m: 1215 subs = list(m.groups()) 1216 for i, sub in enumerate(subs): 1217 if ('{%d}' % (i+1)) in self.subst: 1218 # apply recognizers to subgroup 1219 rep = gdb.types.apply_type_recognizers( 1220 gdb.types.get_type_recognizers(), 1221 gdb.lookup_type(sub)) 1222 if rep: 1223 subs[i] = rep 1224 subs = [None] + subs 1225 return self.subst.format(*subs) 1226 return None 1227 1228 def instantiate(self): 1229 return self._recognizer(self.pattern, self.subst) 1230 1231def add_one_template_type_printer(obj, name, match, subst): 1232 printer = TemplateTypePrinter(name, '^std::' + match + '$', 'std::' + subst) 1233 gdb.types.register_type_printer(obj, printer) 1234 1235class FilteringTypePrinter(object): 1236 def __init__(self, match, name): 1237 self.match = match 1238 self.name = name 1239 self.enabled = True 1240 1241 class _recognizer(object): 1242 def __init__(self, match, name): 1243 self.match = match 1244 self.name = name 1245 self.type_obj = None 1246 1247 def recognize(self, type_obj): 1248 if type_obj.tag is None: 1249 return None 1250 1251 if self.type_obj is None: 1252 if not self.match in type_obj.tag: 1253 # Filter didn't match. 1254 return None 1255 try: 1256 self.type_obj = gdb.lookup_type(self.name).strip_typedefs() 1257 except: 1258 pass 1259 if self.type_obj == type_obj: 1260 return self.name 1261 return None 1262 1263 def instantiate(self): 1264 return self._recognizer(self.match, self.name) 1265 1266def add_one_type_printer(obj, match, name): 1267 printer = FilteringTypePrinter(match, 'std::' + name) 1268 gdb.types.register_type_printer(obj, printer) 1269 1270def register_type_printers(obj): 1271 global _use_type_printing 1272 1273 if not _use_type_printing: 1274 return 1275 1276 for pfx in ('', 'w'): 1277 add_one_type_printer(obj, 'basic_string', pfx + 'string') 1278 add_one_type_printer(obj, 'basic_ios', pfx + 'ios') 1279 add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf') 1280 add_one_type_printer(obj, 'basic_istream', pfx + 'istream') 1281 add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream') 1282 add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream') 1283 add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf') 1284 add_one_type_printer(obj, 'basic_istringstream', 1285 pfx + 'istringstream') 1286 add_one_type_printer(obj, 'basic_ostringstream', 1287 pfx + 'ostringstream') 1288 add_one_type_printer(obj, 'basic_stringstream', 1289 pfx + 'stringstream') 1290 add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf') 1291 add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream') 1292 add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream') 1293 add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream') 1294 add_one_type_printer(obj, 'basic_regex', pfx + 'regex') 1295 add_one_type_printer(obj, 'sub_match', pfx + 'csub_match') 1296 add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match') 1297 add_one_type_printer(obj, 'match_results', pfx + 'cmatch') 1298 add_one_type_printer(obj, 'match_results', pfx + 'smatch') 1299 add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator') 1300 add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator') 1301 add_one_type_printer(obj, 'regex_token_iterator', 1302 pfx + 'cregex_token_iterator') 1303 add_one_type_printer(obj, 'regex_token_iterator', 1304 pfx + 'sregex_token_iterator') 1305 1306 # Note that we can't have a printer for std::wstreampos, because 1307 # it shares the same underlying type as std::streampos. 1308 add_one_type_printer(obj, 'fpos', 'streampos') 1309 add_one_type_printer(obj, 'basic_string', 'u16string') 1310 add_one_type_printer(obj, 'basic_string', 'u32string') 1311 1312 for dur in ('nanoseconds', 'microseconds', 'milliseconds', 1313 'seconds', 'minutes', 'hours'): 1314 add_one_type_printer(obj, 'duration', dur) 1315 1316 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') 1317 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand') 1318 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937') 1319 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64') 1320 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base') 1321 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base') 1322 add_one_type_printer(obj, 'discard_block_engine', 'ranlux24') 1323 add_one_type_printer(obj, 'discard_block_engine', 'ranlux48') 1324 add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b') 1325 1326 # Do not show defaulted template arguments in class templates 1327 add_one_template_type_printer(obj, 'unique_ptr<T>', 1328 'unique_ptr<(.*), std::default_delete<\\1 ?> >', 1329 'unique_ptr<{1}>') 1330 1331 add_one_template_type_printer(obj, 'deque<T>', 1332 'deque<(.*), std::allocator<\\1 ?> >', 1333 'deque<{1}>') 1334 add_one_template_type_printer(obj, 'forward_list<T>', 1335 'forward_list<(.*), std::allocator<\\1 ?> >', 1336 'forward_list<{1}>') 1337 add_one_template_type_printer(obj, 'list<T>', 1338 'list<(.*), std::allocator<\\1 ?> >', 1339 'list<{1}>') 1340 add_one_template_type_printer(obj, 'vector<T>', 1341 'vector<(.*), std::allocator<\\1 ?> >', 1342 'vector<{1}>') 1343 add_one_template_type_printer(obj, 'map<Key, T>', 1344 'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1345 'map<{1}, {2}>') 1346 add_one_template_type_printer(obj, 'multimap<Key, T>', 1347 'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1348 'multimap<{1}, {2}>') 1349 add_one_template_type_printer(obj, 'set<T>', 1350 'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', 1351 'set<{1}>') 1352 add_one_template_type_printer(obj, 'multiset<T>', 1353 'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', 1354 'multiset<{1}>') 1355 add_one_template_type_printer(obj, 'unordered_map<Key, T>', 1356 'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1357 'unordered_map<{1}, {2}>') 1358 add_one_template_type_printer(obj, 'unordered_multimap<Key, T>', 1359 'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1360 'unordered_multimap<{1}, {2}>') 1361 add_one_template_type_printer(obj, 'unordered_set<T>', 1362 'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >', 1363 'unordered_set<{1}>') 1364 add_one_template_type_printer(obj, 'unordered_multiset<T>', 1365 'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >', 1366 'unordered_multiset<{1}>') 1367 1368 # strip the "fundamentals_v1" inline namespace from these types 1369 add_one_template_type_printer(obj, 'optional<T>', 1370 'experimental::fundamentals_v1::optional<(.*)>', 1371 'experimental::optional<{1}>') 1372 add_one_template_type_printer(obj, 'basic_string_view<C>', 1373 'experimental::fundamentals_v1::basic_string_view<(.*), std::char_traits<\\1> >', 1374 'experimental::basic_string_view<{1}>') 1375 1376def register_libstdcxx_printers (obj): 1377 "Register libstdc++ pretty-printers with objfile Obj." 1378 1379 global _use_gdb_pp 1380 global libstdcxx_printer 1381 1382 if _use_gdb_pp: 1383 gdb.printing.register_pretty_printer(obj, libstdcxx_printer) 1384 else: 1385 if obj is None: 1386 obj = gdb 1387 obj.pretty_printers.append(libstdcxx_printer) 1388 1389 register_type_printers(obj) 1390 1391def build_libstdcxx_dictionary (): 1392 global libstdcxx_printer 1393 1394 libstdcxx_printer = Printer("libstdc++-v6") 1395 1396 # For _GLIBCXX_BEGIN_NAMESPACE_VERSION. 1397 vers = '(__7::)?' 1398 # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 1399 container = '(__cxx1998::' + vers + ')?' 1400 1401 # libstdc++ objects requiring pretty-printing. 1402 # In order from: 1403 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html 1404 libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) 1405 libstdcxx_printer.add_version('std::', '__cxx11::basic_string', StdStringPrinter) 1406 libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) 1407 libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) 1408 libstdcxx_printer.add_container('std::', 'list', StdListPrinter) 1409 libstdcxx_printer.add_container('std::__cxx11::', 'list', StdListPrinter) 1410 libstdcxx_printer.add_container('std::', 'map', StdMapPrinter) 1411 libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter) 1412 libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter) 1413 libstdcxx_printer.add_version('std::', 'pair', StdPairPrinter) 1414 libstdcxx_printer.add_version('std::', 'priority_queue', 1415 StdStackOrQueuePrinter) 1416 libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter) 1417 libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter) 1418 libstdcxx_printer.add_container('std::', 'set', StdSetPrinter) 1419 libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter) 1420 libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) 1421 libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) 1422 # vector<bool> 1423 1424 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. 1425 libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) 1426 libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) 1427 libstdcxx_printer.add('std::__debug::list', StdListPrinter) 1428 libstdcxx_printer.add('std::__debug::map', StdMapPrinter) 1429 libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) 1430 libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) 1431 libstdcxx_printer.add('std::__debug::priority_queue', 1432 StdStackOrQueuePrinter) 1433 libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) 1434 libstdcxx_printer.add('std::__debug::set', StdSetPrinter) 1435 libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) 1436 libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) 1437 libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) 1438 1439 # These are the TR1 and C++0x printers. 1440 # For array - the default GDB pretty-printer seems reasonable. 1441 libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter) 1442 libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter) 1443 libstdcxx_printer.add_container('std::', 'unordered_map', 1444 Tr1UnorderedMapPrinter) 1445 libstdcxx_printer.add_container('std::', 'unordered_set', 1446 Tr1UnorderedSetPrinter) 1447 libstdcxx_printer.add_container('std::', 'unordered_multimap', 1448 Tr1UnorderedMapPrinter) 1449 libstdcxx_printer.add_container('std::', 'unordered_multiset', 1450 Tr1UnorderedSetPrinter) 1451 libstdcxx_printer.add_container('std::', 'forward_list', 1452 StdForwardListPrinter) 1453 1454 libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) 1455 libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) 1456 libstdcxx_printer.add_version('std::tr1::', 'unordered_map', 1457 Tr1UnorderedMapPrinter) 1458 libstdcxx_printer.add_version('std::tr1::', 'unordered_set', 1459 Tr1UnorderedSetPrinter) 1460 libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap', 1461 Tr1UnorderedMapPrinter) 1462 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', 1463 Tr1UnorderedSetPrinter) 1464 1465 # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. 1466 # The tr1 namespace printers do not seem to have any debug 1467 # equivalents, so do no register them. 1468 libstdcxx_printer.add('std::__debug::unordered_map', 1469 Tr1UnorderedMapPrinter) 1470 libstdcxx_printer.add('std::__debug::unordered_set', 1471 Tr1UnorderedSetPrinter) 1472 libstdcxx_printer.add('std::__debug::unordered_multimap', 1473 Tr1UnorderedMapPrinter) 1474 libstdcxx_printer.add('std::__debug::unordered_multiset', 1475 Tr1UnorderedSetPrinter) 1476 libstdcxx_printer.add('std::__debug::forward_list', 1477 StdForwardListPrinter) 1478 1479 # Library Fundamentals TS components 1480 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1481 'any', StdExpAnyPrinter) 1482 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1483 'optional', StdExpOptionalPrinter) 1484 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1485 'basic_string_view', StdExpStringViewPrinter) 1486 # Filesystem TS components 1487 libstdcxx_printer.add_version('std::experimental::filesystem::v1::', 1488 'path', StdExpPathPrinter) 1489 libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::', 1490 'path', StdExpPathPrinter) 1491 1492 # Extensions. 1493 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) 1494 1495 if True: 1496 # These shouldn't be necessary, if GDB "print *i" worked. 1497 # But it often doesn't, so here they are. 1498 libstdcxx_printer.add_container('std::', '_List_iterator', 1499 StdListIteratorPrinter) 1500 libstdcxx_printer.add_container('std::', '_List_const_iterator', 1501 StdListIteratorPrinter) 1502 libstdcxx_printer.add_version('std::', '_Rb_tree_iterator', 1503 StdRbtreeIteratorPrinter) 1504 libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator', 1505 StdRbtreeIteratorPrinter) 1506 libstdcxx_printer.add_container('std::', '_Deque_iterator', 1507 StdDequeIteratorPrinter) 1508 libstdcxx_printer.add_container('std::', '_Deque_const_iterator', 1509 StdDequeIteratorPrinter) 1510 libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', 1511 StdVectorIteratorPrinter) 1512 libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', 1513 StdSlistIteratorPrinter) 1514 1515 # Debug (compiled with -D_GLIBCXX_DEBUG) printer 1516 # registrations. The Rb_tree debug iterator when unwrapped 1517 # from the encapsulating __gnu_debug::_Safe_iterator does not 1518 # have the __norm namespace. Just use the existing printer 1519 # registration for that. 1520 libstdcxx_printer.add('__gnu_debug::_Safe_iterator', 1521 StdDebugIteratorPrinter) 1522 libstdcxx_printer.add('std::__norm::_List_iterator', 1523 StdListIteratorPrinter) 1524 libstdcxx_printer.add('std::__norm::_List_const_iterator', 1525 StdListIteratorPrinter) 1526 libstdcxx_printer.add('std::__norm::_Deque_const_iterator', 1527 StdDequeIteratorPrinter) 1528 libstdcxx_printer.add('std::__norm::_Deque_iterator', 1529 StdDequeIteratorPrinter) 1530 1531build_libstdcxx_dictionary () 1532