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 1065# A "regular expression" printer which conforms to the 1066# "SubPrettyPrinter" protocol from gdb.printing. 1067class RxPrinter(object): 1068 def __init__(self, name, function): 1069 super(RxPrinter, self).__init__() 1070 self.name = name 1071 self.function = function 1072 self.enabled = True 1073 1074 def invoke(self, value): 1075 if not self.enabled: 1076 return None 1077 1078 if value.type.code == gdb.TYPE_CODE_REF: 1079 if hasattr(gdb.Value,"referenced_value"): 1080 value = value.referenced_value() 1081 1082 return self.function(self.name, value) 1083 1084# A pretty-printer that conforms to the "PrettyPrinter" protocol from 1085# gdb.printing. It can also be used directly as an old-style printer. 1086class Printer(object): 1087 def __init__(self, name): 1088 super(Printer, self).__init__() 1089 self.name = name 1090 self.subprinters = [] 1091 self.lookup = {} 1092 self.enabled = True 1093 self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') 1094 1095 def add(self, name, function): 1096 # A small sanity check. 1097 # FIXME 1098 if not self.compiled_rx.match(name): 1099 raise ValueError('libstdc++ programming error: "%s" does not match' % name) 1100 printer = RxPrinter(name, function) 1101 self.subprinters.append(printer) 1102 self.lookup[name] = printer 1103 1104 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. 1105 def add_version(self, base, name, function): 1106 self.add(base + name, function) 1107 self.add(base + '__7::' + name, function) 1108 1109 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 1110 def add_container(self, base, name, function): 1111 self.add_version(base, name, function) 1112 self.add_version(base + '__cxx1998::', name, function) 1113 1114 @staticmethod 1115 def get_basic_type(type): 1116 # If it points to a reference, get the reference. 1117 if type.code == gdb.TYPE_CODE_REF: 1118 type = type.target () 1119 1120 # Get the unqualified type, stripped of typedefs. 1121 type = type.unqualified ().strip_typedefs () 1122 1123 return type.tag 1124 1125 def __call__(self, val): 1126 typename = self.get_basic_type(val.type) 1127 if not typename: 1128 return None 1129 1130 # All the types we match are template types, so we can use a 1131 # dictionary. 1132 match = self.compiled_rx.match(typename) 1133 if not match: 1134 return None 1135 1136 basename = match.group(1) 1137 1138 if val.type.code == gdb.TYPE_CODE_REF: 1139 if hasattr(gdb.Value,"referenced_value"): 1140 val = val.referenced_value() 1141 1142 if basename in self.lookup: 1143 return self.lookup[basename].invoke(val) 1144 1145 # Cannot find a pretty printer. Return None. 1146 return None 1147 1148libstdcxx_printer = None 1149 1150class TemplateTypePrinter(object): 1151 r""" 1152 A type printer for class templates. 1153 1154 Recognizes type names that match a regular expression. 1155 Replaces them with a formatted string which can use replacement field 1156 {N} to refer to the \N subgroup of the regex match. 1157 Type printers are recusively applied to the subgroups. 1158 1159 This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >" 1160 and replacing it with "std::vector<{1}>", omitting the template argument 1161 that uses the default type. 1162 """ 1163 1164 def __init__(self, name, pattern, subst): 1165 self.name = name 1166 self.pattern = re.compile(pattern) 1167 self.subst = subst 1168 self.enabled = True 1169 1170 class _recognizer(object): 1171 def __init__(self, pattern, subst): 1172 self.pattern = pattern 1173 self.subst = subst 1174 self.type_obj = None 1175 1176 def recognize(self, type_obj): 1177 if type_obj.tag is None: 1178 return None 1179 1180 m = self.pattern.match(type_obj.tag) 1181 if m: 1182 subs = list(m.groups()) 1183 for i, sub in enumerate(subs): 1184 if ('{%d}' % (i+1)) in self.subst: 1185 # apply recognizers to subgroup 1186 rep = gdb.types.apply_type_recognizers( 1187 gdb.types.get_type_recognizers(), 1188 gdb.lookup_type(sub)) 1189 if rep: 1190 subs[i] = rep 1191 subs = [None] + subs 1192 return self.subst.format(*subs) 1193 return None 1194 1195 def instantiate(self): 1196 return self._recognizer(self.pattern, self.subst) 1197 1198def add_one_template_type_printer(obj, name, match, subst): 1199 printer = TemplateTypePrinter(name, '^std::' + match + '$', 'std::' + subst) 1200 gdb.types.register_type_printer(obj, printer) 1201 1202class FilteringTypePrinter(object): 1203 def __init__(self, match, name): 1204 self.match = match 1205 self.name = name 1206 self.enabled = True 1207 1208 class _recognizer(object): 1209 def __init__(self, match, name): 1210 self.match = match 1211 self.name = name 1212 self.type_obj = None 1213 1214 def recognize(self, type_obj): 1215 if type_obj.tag is None: 1216 return None 1217 1218 if self.type_obj is None: 1219 if not self.match in type_obj.tag: 1220 # Filter didn't match. 1221 return None 1222 try: 1223 self.type_obj = gdb.lookup_type(self.name).strip_typedefs() 1224 except: 1225 pass 1226 if self.type_obj == type_obj: 1227 return self.name 1228 return None 1229 1230 def instantiate(self): 1231 return self._recognizer(self.match, self.name) 1232 1233def add_one_type_printer(obj, match, name): 1234 printer = FilteringTypePrinter(match, 'std::' + name) 1235 gdb.types.register_type_printer(obj, printer) 1236 1237def register_type_printers(obj): 1238 global _use_type_printing 1239 1240 if not _use_type_printing: 1241 return 1242 1243 for pfx in ('', 'w'): 1244 add_one_type_printer(obj, 'basic_string', pfx + 'string') 1245 add_one_type_printer(obj, 'basic_ios', pfx + 'ios') 1246 add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf') 1247 add_one_type_printer(obj, 'basic_istream', pfx + 'istream') 1248 add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream') 1249 add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream') 1250 add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf') 1251 add_one_type_printer(obj, 'basic_istringstream', 1252 pfx + 'istringstream') 1253 add_one_type_printer(obj, 'basic_ostringstream', 1254 pfx + 'ostringstream') 1255 add_one_type_printer(obj, 'basic_stringstream', 1256 pfx + 'stringstream') 1257 add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf') 1258 add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream') 1259 add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream') 1260 add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream') 1261 add_one_type_printer(obj, 'basic_regex', pfx + 'regex') 1262 add_one_type_printer(obj, 'sub_match', pfx + 'csub_match') 1263 add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match') 1264 add_one_type_printer(obj, 'match_results', pfx + 'cmatch') 1265 add_one_type_printer(obj, 'match_results', pfx + 'smatch') 1266 add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator') 1267 add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator') 1268 add_one_type_printer(obj, 'regex_token_iterator', 1269 pfx + 'cregex_token_iterator') 1270 add_one_type_printer(obj, 'regex_token_iterator', 1271 pfx + 'sregex_token_iterator') 1272 1273 # Note that we can't have a printer for std::wstreampos, because 1274 # it shares the same underlying type as std::streampos. 1275 add_one_type_printer(obj, 'fpos', 'streampos') 1276 add_one_type_printer(obj, 'basic_string', 'u16string') 1277 add_one_type_printer(obj, 'basic_string', 'u32string') 1278 1279 for dur in ('nanoseconds', 'microseconds', 'milliseconds', 1280 'seconds', 'minutes', 'hours'): 1281 add_one_type_printer(obj, 'duration', dur) 1282 1283 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') 1284 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand') 1285 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937') 1286 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64') 1287 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base') 1288 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base') 1289 add_one_type_printer(obj, 'discard_block_engine', 'ranlux24') 1290 add_one_type_printer(obj, 'discard_block_engine', 'ranlux48') 1291 add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b') 1292 1293 # Do not show defaulted template arguments in class templates 1294 add_one_template_type_printer(obj, 'unique_ptr<T>', 1295 'unique_ptr<(.*), std::default_delete<\\1 ?> >', 1296 'unique_ptr<{1}>') 1297 1298 add_one_template_type_printer(obj, 'deque<T>', 1299 'deque<(.*), std::allocator<\\1 ?> >', 1300 'deque<{1}>') 1301 add_one_template_type_printer(obj, 'forward_list<T>', 1302 'forward_list<(.*), std::allocator<\\1 ?> >', 1303 'forward_list<{1}>') 1304 add_one_template_type_printer(obj, 'list<T>', 1305 'list<(.*), std::allocator<\\1 ?> >', 1306 'list<{1}>') 1307 add_one_template_type_printer(obj, 'vector<T>', 1308 'vector<(.*), std::allocator<\\1 ?> >', 1309 'vector<{1}>') 1310 add_one_template_type_printer(obj, 'map<Key, T>', 1311 'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1312 'map<{1}, {2}>') 1313 add_one_template_type_printer(obj, 'multimap<Key, T>', 1314 'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1315 'multimap<{1}, {2}>') 1316 add_one_template_type_printer(obj, 'set<T>', 1317 'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', 1318 'set<{1}>') 1319 add_one_template_type_printer(obj, 'multiset<T>', 1320 'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', 1321 'multiset<{1}>') 1322 add_one_template_type_printer(obj, 'unordered_map<Key, T>', 1323 'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1324 'unordered_map<{1}, {2}>') 1325 add_one_template_type_printer(obj, 'unordered_multimap<Key, T>', 1326 'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 1327 'unordered_multimap<{1}, {2}>') 1328 add_one_template_type_printer(obj, 'unordered_set<T>', 1329 'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >', 1330 'unordered_set<{1}>') 1331 add_one_template_type_printer(obj, 'unordered_multiset<T>', 1332 'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >', 1333 'unordered_multiset<{1}>') 1334 1335 # strip the "fundamentals_v1" inline namespace from these types 1336 add_one_template_type_printer(obj, 'optional<T>', 1337 'experimental::fundamentals_v1::optional<(.*)>', 1338 'experimental::optional<\\1>') 1339 add_one_template_type_printer(obj, 'basic_string_view<C>', 1340 'experimental::fundamentals_v1::basic_string_view<(.*), std::char_traits<\\1> >', 1341 'experimental::basic_string_view<\\1>') 1342 1343def register_libstdcxx_printers (obj): 1344 "Register libstdc++ pretty-printers with objfile Obj." 1345 1346 global _use_gdb_pp 1347 global libstdcxx_printer 1348 1349 if _use_gdb_pp: 1350 gdb.printing.register_pretty_printer(obj, libstdcxx_printer) 1351 else: 1352 if obj is None: 1353 obj = gdb 1354 obj.pretty_printers.append(libstdcxx_printer) 1355 1356 register_type_printers(obj) 1357 1358def build_libstdcxx_dictionary (): 1359 global libstdcxx_printer 1360 1361 libstdcxx_printer = Printer("libstdc++-v6") 1362 1363 # For _GLIBCXX_BEGIN_NAMESPACE_VERSION. 1364 vers = '(__7::)?' 1365 # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 1366 container = '(__cxx1998::' + vers + ')?' 1367 1368 # libstdc++ objects requiring pretty-printing. 1369 # In order from: 1370 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html 1371 libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) 1372 libstdcxx_printer.add_version('std::', '__cxx11::basic_string', StdStringPrinter) 1373 libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) 1374 libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) 1375 libstdcxx_printer.add_container('std::', 'list', StdListPrinter) 1376 libstdcxx_printer.add_container('std::__cxx11::', 'list', StdListPrinter) 1377 libstdcxx_printer.add_container('std::', 'map', StdMapPrinter) 1378 libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter) 1379 libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter) 1380 libstdcxx_printer.add_version('std::', 'priority_queue', 1381 StdStackOrQueuePrinter) 1382 libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter) 1383 libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter) 1384 libstdcxx_printer.add_container('std::', 'set', StdSetPrinter) 1385 libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter) 1386 libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) 1387 libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) 1388 # vector<bool> 1389 1390 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. 1391 libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) 1392 libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) 1393 libstdcxx_printer.add('std::__debug::list', StdListPrinter) 1394 libstdcxx_printer.add('std::__debug::map', StdMapPrinter) 1395 libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) 1396 libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) 1397 libstdcxx_printer.add('std::__debug::priority_queue', 1398 StdStackOrQueuePrinter) 1399 libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) 1400 libstdcxx_printer.add('std::__debug::set', StdSetPrinter) 1401 libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) 1402 libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) 1403 libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) 1404 1405 # These are the TR1 and C++0x printers. 1406 # For array - the default GDB pretty-printer seems reasonable. 1407 libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter) 1408 libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter) 1409 libstdcxx_printer.add_container('std::', 'unordered_map', 1410 Tr1UnorderedMapPrinter) 1411 libstdcxx_printer.add_container('std::', 'unordered_set', 1412 Tr1UnorderedSetPrinter) 1413 libstdcxx_printer.add_container('std::', 'unordered_multimap', 1414 Tr1UnorderedMapPrinter) 1415 libstdcxx_printer.add_container('std::', 'unordered_multiset', 1416 Tr1UnorderedSetPrinter) 1417 libstdcxx_printer.add_container('std::', 'forward_list', 1418 StdForwardListPrinter) 1419 1420 libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) 1421 libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) 1422 libstdcxx_printer.add_version('std::tr1::', 'unordered_map', 1423 Tr1UnorderedMapPrinter) 1424 libstdcxx_printer.add_version('std::tr1::', 'unordered_set', 1425 Tr1UnorderedSetPrinter) 1426 libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap', 1427 Tr1UnorderedMapPrinter) 1428 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', 1429 Tr1UnorderedSetPrinter) 1430 1431 # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. 1432 # The tr1 namespace printers do not seem to have any debug 1433 # equivalents, so do no register them. 1434 libstdcxx_printer.add('std::__debug::unordered_map', 1435 Tr1UnorderedMapPrinter) 1436 libstdcxx_printer.add('std::__debug::unordered_set', 1437 Tr1UnorderedSetPrinter) 1438 libstdcxx_printer.add('std::__debug::unordered_multimap', 1439 Tr1UnorderedMapPrinter) 1440 libstdcxx_printer.add('std::__debug::unordered_multiset', 1441 Tr1UnorderedSetPrinter) 1442 libstdcxx_printer.add('std::__debug::forward_list', 1443 StdForwardListPrinter) 1444 1445 # Library Fundamentals TS components 1446 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1447 'any', StdExpAnyPrinter) 1448 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1449 'optional', StdExpOptionalPrinter) 1450 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 1451 'basic_string_view', StdExpStringViewPrinter) 1452 # Filesystem TS components 1453 libstdcxx_printer.add_version('std::experimental::filesystem::v1::', 1454 'path', StdExpPathPrinter) 1455 libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::', 1456 'path', StdExpPathPrinter) 1457 1458 # Extensions. 1459 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) 1460 1461 if True: 1462 # These shouldn't be necessary, if GDB "print *i" worked. 1463 # But it often doesn't, so here they are. 1464 libstdcxx_printer.add_container('std::', '_List_iterator', 1465 StdListIteratorPrinter) 1466 libstdcxx_printer.add_container('std::', '_List_const_iterator', 1467 StdListIteratorPrinter) 1468 libstdcxx_printer.add_version('std::', '_Rb_tree_iterator', 1469 StdRbtreeIteratorPrinter) 1470 libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator', 1471 StdRbtreeIteratorPrinter) 1472 libstdcxx_printer.add_container('std::', '_Deque_iterator', 1473 StdDequeIteratorPrinter) 1474 libstdcxx_printer.add_container('std::', '_Deque_const_iterator', 1475 StdDequeIteratorPrinter) 1476 libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', 1477 StdVectorIteratorPrinter) 1478 libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', 1479 StdSlistIteratorPrinter) 1480 1481 # Debug (compiled with -D_GLIBCXX_DEBUG) printer 1482 # registrations. The Rb_tree debug iterator when unwrapped 1483 # from the encapsulating __gnu_debug::_Safe_iterator does not 1484 # have the __norm namespace. Just use the existing printer 1485 # registration for that. 1486 libstdcxx_printer.add('__gnu_debug::_Safe_iterator', 1487 StdDebugIteratorPrinter) 1488 libstdcxx_printer.add('std::__norm::_List_iterator', 1489 StdListIteratorPrinter) 1490 libstdcxx_printer.add('std::__norm::_List_const_iterator', 1491 StdListIteratorPrinter) 1492 libstdcxx_printer.add('std::__norm::_Deque_const_iterator', 1493 StdDequeIteratorPrinter) 1494 libstdcxx_printer.add('std::__norm::_Deque_iterator', 1495 StdDequeIteratorPrinter) 1496 1497build_libstdcxx_dictionary () 1498