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