1 # Pretty-printers for libstc++. 2 3 # Copyright (C) 2008, 2009, 2010, 2011, 2012 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 18 import gdb 19 import itertools 20 import re 21 22 # Try to use the new-style pretty-printing if available. 23 _use_gdb_pp = True 24 try: 25 import gdb.printing 26 except ImportError: 27 _use_gdb_pp = False 28 29 # Starting with the type ORIG, search for the member type NAME. This 30 # handles searching upward through superclasses. This is needed to 31 # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615. 32 def find_type(orig, name): 33 typ = orig.strip_typedefs() 34 while True: 35 search = str(typ) + '::' + name 36 try: 37 return gdb.lookup_type(search) 38 except RuntimeError: 39 pass 40 # The type was not found, so try the superclass. We only need 41 # to check the first superclass, so we don't bother with 42 # anything fancier here. 43 field = typ.fields()[0] 44 if not field.is_base_class: 45 raise ValueError, "Cannot find type %s::%s" % (str(orig), name) 46 typ = field.type 47 48 class SharedPointerPrinter: 49 "Print a shared_ptr or weak_ptr" 50 51 def __init__ (self, typename, val): 52 self.typename = typename 53 self.val = val 54 55 def to_string (self): 56 state = 'empty' 57 refcounts = self.val['_M_refcount']['_M_pi'] 58 if refcounts != 0: 59 usecount = refcounts['_M_use_count'] 60 weakcount = refcounts['_M_weak_count'] 61 if usecount == 0: 62 state = 'expired, weak %d' % weakcount 63 else: 64 state = 'count %d, weak %d' % (usecount, weakcount - 1) 65 return '%s (%s) %s' % (self.typename, state, self.val['_M_ptr']) 66 67 class UniquePointerPrinter: 68 "Print a unique_ptr" 69 70 def __init__ (self, typename, val): 71 self.val = val 72 73 def to_string (self): 74 return self.val['_M_t'] 75 76 class StdListPrinter: 77 "Print a std::list" 78 79 class _iterator: 80 def __init__(self, nodetype, head): 81 self.nodetype = nodetype 82 self.base = head['_M_next'] 83 self.head = head.address 84 self.count = 0 85 86 def __iter__(self): 87 return self 88 89 def next(self): 90 if self.base == self.head: 91 raise StopIteration 92 elt = self.base.cast(self.nodetype).dereference() 93 self.base = elt['_M_next'] 94 count = self.count 95 self.count = self.count + 1 96 return ('[%d]' % count, elt['_M_data']) 97 98 def __init__(self, typename, val): 99 self.typename = typename 100 self.val = val 101 102 def children(self): 103 nodetype = find_type(self.val.type, '_Node') 104 nodetype = nodetype.strip_typedefs().pointer() 105 return self._iterator(nodetype, self.val['_M_impl']['_M_node']) 106 107 def to_string(self): 108 if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: 109 return 'empty %s' % (self.typename) 110 return '%s' % (self.typename) 111 112 class StdListIteratorPrinter: 113 "Print std::list::iterator" 114 115 def __init__(self, typename, val): 116 self.val = val 117 self.typename = typename 118 119 def to_string(self): 120 nodetype = find_type(self.val.type, '_Node') 121 nodetype = nodetype.strip_typedefs().pointer() 122 return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] 123 124 class StdSlistPrinter: 125 "Print a __gnu_cxx::slist" 126 127 class _iterator: 128 def __init__(self, nodetype, head): 129 self.nodetype = nodetype 130 self.base = head['_M_head']['_M_next'] 131 self.count = 0 132 133 def __iter__(self): 134 return self 135 136 def next(self): 137 if self.base == 0: 138 raise StopIteration 139 elt = self.base.cast(self.nodetype).dereference() 140 self.base = elt['_M_next'] 141 count = self.count 142 self.count = self.count + 1 143 return ('[%d]' % count, elt['_M_data']) 144 145 def __init__(self, typename, val): 146 self.val = val 147 148 def children(self): 149 nodetype = find_type(self.val.type, '_Node') 150 nodetype = nodetype.strip_typedefs().pointer() 151 return self._iterator(nodetype, self.val) 152 153 def to_string(self): 154 if self.val['_M_head']['_M_next'] == 0: 155 return 'empty __gnu_cxx::slist' 156 return '__gnu_cxx::slist' 157 158 class StdSlistIteratorPrinter: 159 "Print __gnu_cxx::slist::iterator" 160 161 def __init__(self, typename, val): 162 self.val = val 163 164 def to_string(self): 165 nodetype = find_type(self.val.type, '_Node') 166 nodetype = nodetype.strip_typedefs().pointer() 167 return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] 168 169 class StdVectorPrinter: 170 "Print a std::vector" 171 172 class _iterator: 173 def __init__ (self, start, finish, bitvec): 174 self.bitvec = bitvec 175 if bitvec: 176 self.item = start['_M_p'] 177 self.so = start['_M_offset'] 178 self.finish = finish['_M_p'] 179 self.fo = finish['_M_offset'] 180 itype = self.item.dereference().type 181 self.isize = 8 * itype.sizeof 182 else: 183 self.item = start 184 self.finish = finish 185 self.count = 0 186 187 def __iter__(self): 188 return self 189 190 def next(self): 191 count = self.count 192 self.count = self.count + 1 193 if self.bitvec: 194 if self.item == self.finish and self.so >= self.fo: 195 raise StopIteration 196 elt = self.item.dereference() 197 if elt & (1 << self.so): 198 obit = 1 199 else: 200 obit = 0 201 self.so = self.so + 1 202 if self.so >= self.isize: 203 self.item = self.item + 1 204 self.so = 0 205 return ('[%d]' % count, obit) 206 else: 207 if self.item == self.finish: 208 raise StopIteration 209 elt = self.item.dereference() 210 self.item = self.item + 1 211 return ('[%d]' % count, elt) 212 213 def __init__(self, typename, val): 214 self.typename = typename 215 self.val = val 216 self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL 217 218 def children(self): 219 return self._iterator(self.val['_M_impl']['_M_start'], 220 self.val['_M_impl']['_M_finish'], 221 self.is_bool) 222 223 def to_string(self): 224 start = self.val['_M_impl']['_M_start'] 225 finish = self.val['_M_impl']['_M_finish'] 226 end = self.val['_M_impl']['_M_end_of_storage'] 227 if self.is_bool: 228 start = self.val['_M_impl']['_M_start']['_M_p'] 229 so = self.val['_M_impl']['_M_start']['_M_offset'] 230 finish = self.val['_M_impl']['_M_finish']['_M_p'] 231 fo = self.val['_M_impl']['_M_finish']['_M_offset'] 232 itype = start.dereference().type 233 bl = 8 * itype.sizeof 234 length = (bl - so) + bl * ((finish - start) - 1) + fo 235 capacity = bl * (end - start) 236 return ('%s<bool> of length %d, capacity %d' 237 % (self.typename, int (length), int (capacity))) 238 else: 239 return ('%s of length %d, capacity %d' 240 % (self.typename, int (finish - start), int (end - start))) 241 242 def display_hint(self): 243 return 'array' 244 245 class StdVectorIteratorPrinter: 246 "Print std::vector::iterator" 247 248 def __init__(self, typename, val): 249 self.val = val 250 251 def to_string(self): 252 return self.val['_M_current'].dereference() 253 254 class StdTuplePrinter: 255 "Print a std::tuple" 256 257 class _iterator: 258 def __init__ (self, head): 259 self.head = head 260 261 # Set the base class as the initial head of the 262 # tuple. 263 nodes = self.head.type.fields () 264 if len (nodes) == 1: 265 # Set the actual head to the first pair. 266 self.head = self.head.cast (nodes[0].type) 267 elif len (nodes) != 0: 268 raise ValueError, "Top of tuple tree does not consist of a single node." 269 self.count = 0 270 271 def __iter__ (self): 272 return self 273 274 def next (self): 275 nodes = self.head.type.fields () 276 # Check for further recursions in the inheritance tree. 277 if len (nodes) == 0: 278 raise StopIteration 279 # Check that this iteration has an expected structure. 280 if len (nodes) != 2: 281 raise ValueError, "Cannot parse more than 2 nodes in a tuple tree." 282 283 # - Left node is the next recursion parent. 284 # - Right node is the actual class contained in the tuple. 285 286 # Process right node. 287 impl = self.head.cast (nodes[1].type) 288 289 # Process left node and set it as head. 290 self.head = self.head.cast (nodes[0].type) 291 self.count = self.count + 1 292 293 # Finally, check the implementation. If it is 294 # wrapped in _M_head_impl return that, otherwise return 295 # the value "as is". 296 fields = impl.type.fields () 297 if len (fields) < 1 or fields[0].name != "_M_head_impl": 298 return ('[%d]' % self.count, impl) 299 else: 300 return ('[%d]' % self.count, impl['_M_head_impl']) 301 302 def __init__ (self, typename, val): 303 self.typename = typename 304 self.val = val; 305 306 def children (self): 307 return self._iterator (self.val) 308 309 def to_string (self): 310 if len (self.val.type.fields ()) == 0: 311 return 'empty %s' % (self.typename) 312 return '%s containing' % (self.typename) 313 314 class StdStackOrQueuePrinter: 315 "Print a std::stack or std::queue" 316 317 def __init__ (self, typename, val): 318 self.typename = typename 319 self.visualizer = gdb.default_visualizer(val['c']) 320 321 def children (self): 322 return self.visualizer.children() 323 324 def to_string (self): 325 return '%s wrapping: %s' % (self.typename, 326 self.visualizer.to_string()) 327 328 def display_hint (self): 329 if hasattr (self.visualizer, 'display_hint'): 330 return self.visualizer.display_hint () 331 return None 332 333 class RbtreeIterator: 334 def __init__(self, rbtree): 335 self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] 336 self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] 337 self.count = 0 338 339 def __iter__(self): 340 return self 341 342 def __len__(self): 343 return int (self.size) 344 345 def next(self): 346 if self.count == self.size: 347 raise StopIteration 348 result = self.node 349 self.count = self.count + 1 350 if self.count < self.size: 351 # Compute the next node. 352 node = self.node 353 if node.dereference()['_M_right']: 354 node = node.dereference()['_M_right'] 355 while node.dereference()['_M_left']: 356 node = node.dereference()['_M_left'] 357 else: 358 parent = node.dereference()['_M_parent'] 359 while node == parent.dereference()['_M_right']: 360 node = parent 361 parent = parent.dereference()['_M_parent'] 362 if node.dereference()['_M_right'] != parent: 363 node = parent 364 self.node = node 365 return result 366 367 # This is a pretty printer for std::_Rb_tree_iterator (which is 368 # std::map::iterator), and has nothing to do with the RbtreeIterator 369 # class above. 370 class StdRbtreeIteratorPrinter: 371 "Print std::map::iterator" 372 373 def __init__ (self, typename, val): 374 self.val = val 375 376 def to_string (self): 377 typename = str(self.val.type.strip_typedefs()) + '::_Link_type' 378 nodetype = gdb.lookup_type(typename).strip_typedefs() 379 return self.val.cast(nodetype).dereference()['_M_value_field'] 380 381 class StdDebugIteratorPrinter: 382 "Print a debug enabled version of an iterator" 383 384 def __init__ (self, typename, val): 385 self.val = val 386 387 # Just strip away the encapsulating __gnu_debug::_Safe_iterator 388 # and return the wrapped iterator value. 389 def to_string (self): 390 itype = self.val.type.template_argument(0) 391 return self.val['_M_current'].cast(itype) 392 393 class StdMapPrinter: 394 "Print a std::map or std::multimap" 395 396 # Turn an RbtreeIterator into a pretty-print iterator. 397 class _iter: 398 def __init__(self, rbiter, type): 399 self.rbiter = rbiter 400 self.count = 0 401 self.type = type 402 403 def __iter__(self): 404 return self 405 406 def next(self): 407 if self.count % 2 == 0: 408 n = self.rbiter.next() 409 n = n.cast(self.type).dereference()['_M_value_field'] 410 self.pair = n 411 item = n['first'] 412 else: 413 item = self.pair['second'] 414 result = ('[%d]' % self.count, item) 415 self.count = self.count + 1 416 return result 417 418 def __init__ (self, typename, val): 419 self.typename = typename 420 self.val = val 421 422 def to_string (self): 423 return '%s with %d elements' % (self.typename, 424 len (RbtreeIterator (self.val))) 425 426 def children (self): 427 rep_type = find_type(self.val.type, '_Rep_type') 428 node = find_type(rep_type, '_Link_type') 429 node = node.strip_typedefs() 430 return self._iter (RbtreeIterator (self.val), node) 431 432 def display_hint (self): 433 return 'map' 434 435 class StdSetPrinter: 436 "Print a std::set or std::multiset" 437 438 # Turn an RbtreeIterator into a pretty-print iterator. 439 class _iter: 440 def __init__(self, rbiter, type): 441 self.rbiter = rbiter 442 self.count = 0 443 self.type = type 444 445 def __iter__(self): 446 return self 447 448 def next(self): 449 item = self.rbiter.next() 450 item = item.cast(self.type).dereference()['_M_value_field'] 451 # FIXME: this is weird ... what to do? 452 # Maybe a 'set' display hint? 453 result = ('[%d]' % self.count, item) 454 self.count = self.count + 1 455 return result 456 457 def __init__ (self, typename, val): 458 self.typename = typename 459 self.val = val 460 461 def to_string (self): 462 return '%s with %d elements' % (self.typename, 463 len (RbtreeIterator (self.val))) 464 465 def children (self): 466 rep_type = find_type(self.val.type, '_Rep_type') 467 node = find_type(rep_type, '_Link_type') 468 node = node.strip_typedefs() 469 return self._iter (RbtreeIterator (self.val), node) 470 471 class StdBitsetPrinter: 472 "Print a std::bitset" 473 474 def __init__(self, typename, val): 475 self.typename = typename 476 self.val = val 477 478 def to_string (self): 479 # If template_argument handled values, we could print the 480 # size. Or we could use a regexp on the type. 481 return '%s' % (self.typename) 482 483 def children (self): 484 words = self.val['_M_w'] 485 wtype = words.type 486 487 # The _M_w member can be either an unsigned long, or an 488 # array. This depends on the template specialization used. 489 # If it is a single long, convert to a single element list. 490 if wtype.code == gdb.TYPE_CODE_ARRAY: 491 tsize = wtype.target ().sizeof 492 else: 493 words = [words] 494 tsize = wtype.sizeof 495 496 nwords = wtype.sizeof / tsize 497 result = [] 498 byte = 0 499 while byte < nwords: 500 w = words[byte] 501 bit = 0 502 while w != 0: 503 if (w & 1) != 0: 504 # Another spot where we could use 'set'? 505 result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) 506 bit = bit + 1 507 w = w >> 1 508 byte = byte + 1 509 return result 510 511 class StdDequePrinter: 512 "Print a std::deque" 513 514 class _iter: 515 def __init__(self, node, start, end, last, buffer_size): 516 self.node = node 517 self.p = start 518 self.end = end 519 self.last = last 520 self.buffer_size = buffer_size 521 self.count = 0 522 523 def __iter__(self): 524 return self 525 526 def next(self): 527 if self.p == self.last: 528 raise StopIteration 529 530 result = ('[%d]' % self.count, self.p.dereference()) 531 self.count = self.count + 1 532 533 # Advance the 'cur' pointer. 534 self.p = self.p + 1 535 if self.p == self.end: 536 # If we got to the end of this bucket, move to the 537 # next bucket. 538 self.node = self.node + 1 539 self.p = self.node[0] 540 self.end = self.p + self.buffer_size 541 542 return result 543 544 def __init__(self, typename, val): 545 self.typename = typename 546 self.val = val 547 self.elttype = val.type.template_argument(0) 548 size = self.elttype.sizeof 549 if size < 512: 550 self.buffer_size = int (512 / size) 551 else: 552 self.buffer_size = 1 553 554 def to_string(self): 555 start = self.val['_M_impl']['_M_start'] 556 end = self.val['_M_impl']['_M_finish'] 557 558 delta_n = end['_M_node'] - start['_M_node'] - 1 559 delta_s = start['_M_last'] - start['_M_cur'] 560 delta_e = end['_M_cur'] - end['_M_first'] 561 562 size = self.buffer_size * delta_n + delta_s + delta_e 563 564 return '%s with %d elements' % (self.typename, long (size)) 565 566 def children(self): 567 start = self.val['_M_impl']['_M_start'] 568 end = self.val['_M_impl']['_M_finish'] 569 return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], 570 end['_M_cur'], self.buffer_size) 571 572 def display_hint (self): 573 return 'array' 574 575 class StdDequeIteratorPrinter: 576 "Print std::deque::iterator" 577 578 def __init__(self, typename, val): 579 self.val = val 580 581 def to_string(self): 582 return self.val['_M_cur'].dereference() 583 584 class StdStringPrinter: 585 "Print a std::basic_string of some kind" 586 587 def __init__(self, typename, val): 588 self.val = val 589 590 def to_string(self): 591 # Make sure &string works, too. 592 type = self.val.type 593 if type.code == gdb.TYPE_CODE_REF: 594 type = type.target () 595 596 # Calculate the length of the string so that to_string returns 597 # the string according to length, not according to first null 598 # encountered. 599 ptr = self.val ['_M_dataplus']['_M_p'] 600 realtype = type.unqualified ().strip_typedefs () 601 reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () 602 header = ptr.cast(reptype) - 1 603 len = header.dereference ()['_M_length'] 604 if hasattr(ptr, "lazy_string"): 605 return ptr.lazy_string (length = len) 606 return ptr.string (length = len) 607 608 def display_hint (self): 609 return 'string' 610 611 class Tr1HashtableIterator: 612 def __init__ (self, hash): 613 self.node = hash['_M_before_begin']['_M_nxt'] 614 self.node_type = find_type(hash.type, '_Node').pointer() 615 616 def __iter__ (self): 617 return self 618 619 def next (self): 620 if self.node == 0: 621 raise StopIteration 622 node = self.node.cast(self.node_type) 623 result = node.dereference()['_M_v'] 624 self.node = node.dereference()['_M_nxt'] 625 return result 626 627 class Tr1UnorderedSetPrinter: 628 "Print a tr1::unordered_set" 629 630 def __init__ (self, typename, val): 631 self.typename = typename 632 self.val = val 633 634 def to_string (self): 635 return '%s with %d elements' % (self.typename, self.val['_M_element_count']) 636 637 @staticmethod 638 def format_count (i): 639 return '[%d]' % i 640 641 def children (self): 642 counter = itertools.imap (self.format_count, itertools.count()) 643 return itertools.izip (counter, Tr1HashtableIterator (self.val)) 644 645 class Tr1UnorderedMapPrinter: 646 "Print a tr1::unordered_map" 647 648 def __init__ (self, typename, val): 649 self.typename = typename 650 self.val = val 651 652 def to_string (self): 653 return '%s with %d elements' % (self.typename, self.val['_M_element_count']) 654 655 @staticmethod 656 def flatten (list): 657 for elt in list: 658 for i in elt: 659 yield i 660 661 @staticmethod 662 def format_one (elt): 663 return (elt['first'], elt['second']) 664 665 @staticmethod 666 def format_count (i): 667 return '[%d]' % i 668 669 def children (self): 670 counter = itertools.imap (self.format_count, itertools.count()) 671 # Map over the hash table and flatten the result. 672 data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.val))) 673 # Zip the two iterators together. 674 return itertools.izip (counter, data) 675 676 def display_hint (self): 677 return 'map' 678 679 class StdForwardListPrinter: 680 "Print a std::forward_list" 681 682 class _iterator: 683 def __init__(self, nodetype, head): 684 self.nodetype = nodetype 685 self.base = head['_M_next'] 686 self.count = 0 687 688 def __iter__(self): 689 return self 690 691 def next(self): 692 if self.base == 0: 693 raise StopIteration 694 elt = self.base.cast(self.nodetype).dereference() 695 self.base = elt['_M_next'] 696 count = self.count 697 self.count = self.count + 1 698 return ('[%d]' % count, elt['_M_value']) 699 700 def __init__(self, typename, val): 701 self.val = val 702 self.typename = typename 703 704 def children(self): 705 nodetype = find_type(self.val.type, '_Node') 706 nodetype = nodetype.strip_typedefs().pointer() 707 return self._iterator(nodetype, self.val['_M_impl']['_M_head']) 708 709 def to_string(self): 710 if self.val['_M_impl']['_M_head']['_M_next'] == 0: 711 return 'empty %s' % (self.typename) 712 return '%s' % (self.typename) 713 714 715 # A "regular expression" printer which conforms to the 716 # "SubPrettyPrinter" protocol from gdb.printing. 717 class RxPrinter(object): 718 def __init__(self, name, function): 719 super(RxPrinter, self).__init__() 720 self.name = name 721 self.function = function 722 self.enabled = True 723 724 def invoke(self, value): 725 if not self.enabled: 726 return None 727 return self.function(self.name, value) 728 729 # A pretty-printer that conforms to the "PrettyPrinter" protocol from 730 # gdb.printing. It can also be used directly as an old-style printer. 731 class Printer(object): 732 def __init__(self, name): 733 super(Printer, self).__init__() 734 self.name = name 735 self.subprinters = [] 736 self.lookup = {} 737 self.enabled = True 738 self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') 739 740 def add(self, name, function): 741 # A small sanity check. 742 # FIXME 743 if not self.compiled_rx.match(name + '<>'): 744 raise ValueError, 'libstdc++ programming error: "%s" does not match' % name 745 printer = RxPrinter(name, function) 746 self.subprinters.append(printer) 747 self.lookup[name] = printer 748 749 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. 750 def add_version(self, base, name, function): 751 self.add(base + name, function) 752 self.add(base + '__7::' + name, function) 753 754 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 755 def add_container(self, base, name, function): 756 self.add_version(base, name, function) 757 self.add_version(base + '__cxx1998::', name, function) 758 759 @staticmethod 760 def get_basic_type(type): 761 # If it points to a reference, get the reference. 762 if type.code == gdb.TYPE_CODE_REF: 763 type = type.target () 764 765 # Get the unqualified type, stripped of typedefs. 766 type = type.unqualified ().strip_typedefs () 767 768 return type.tag 769 770 def __call__(self, val): 771 typename = self.get_basic_type(val.type) 772 if not typename: 773 return None 774 775 # All the types we match are template types, so we can use a 776 # dictionary. 777 match = self.compiled_rx.match(typename) 778 if not match: 779 return None 780 781 basename = match.group(1) 782 if basename in self.lookup: 783 return self.lookup[basename].invoke(val) 784 785 # Cannot find a pretty printer. Return None. 786 return None 787 788 libstdcxx_printer = None 789 790 def register_libstdcxx_printers (obj): 791 "Register libstdc++ pretty-printers with objfile Obj." 792 793 global _use_gdb_pp 794 global libstdcxx_printer 795 796 if _use_gdb_pp: 797 gdb.printing.register_pretty_printer(obj, libstdcxx_printer) 798 else: 799 if obj is None: 800 obj = gdb 801 obj.pretty_printers.append(libstdcxx_printer) 802 803 def build_libstdcxx_dictionary (): 804 global libstdcxx_printer 805 806 libstdcxx_printer = Printer("libstdc++-v6") 807 808 # For _GLIBCXX_BEGIN_NAMESPACE_VERSION. 809 vers = '(__7::)?' 810 # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER. 811 container = '(__cxx1998::' + vers + ')?' 812 813 # libstdc++ objects requiring pretty-printing. 814 # In order from: 815 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html 816 libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) 817 libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) 818 libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) 819 libstdcxx_printer.add_container('std::', 'list', StdListPrinter) 820 libstdcxx_printer.add_container('std::', 'map', StdMapPrinter) 821 libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter) 822 libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter) 823 libstdcxx_printer.add_version('std::', 'priority_queue', 824 StdStackOrQueuePrinter) 825 libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter) 826 libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter) 827 libstdcxx_printer.add_container('std::', 'set', StdSetPrinter) 828 libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter) 829 libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter) 830 libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter) 831 # vector<bool> 832 833 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. 834 libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) 835 libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) 836 libstdcxx_printer.add('std::__debug::list', StdListPrinter) 837 libstdcxx_printer.add('std::__debug::map', StdMapPrinter) 838 libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) 839 libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) 840 libstdcxx_printer.add('std::__debug::priority_queue', 841 StdStackOrQueuePrinter) 842 libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) 843 libstdcxx_printer.add('std::__debug::set', StdSetPrinter) 844 libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) 845 libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) 846 libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) 847 848 # These are the TR1 and C++0x printers. 849 # For array - the default GDB pretty-printer seems reasonable. 850 libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter) 851 libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter) 852 libstdcxx_printer.add_container('std::', 'unordered_map', 853 Tr1UnorderedMapPrinter) 854 libstdcxx_printer.add_container('std::', 'unordered_set', 855 Tr1UnorderedSetPrinter) 856 libstdcxx_printer.add_container('std::', 'unordered_multimap', 857 Tr1UnorderedMapPrinter) 858 libstdcxx_printer.add_container('std::', 'unordered_multiset', 859 Tr1UnorderedSetPrinter) 860 libstdcxx_printer.add_container('std::', 'forward_list', 861 StdForwardListPrinter) 862 863 libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter) 864 libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter) 865 libstdcxx_printer.add_version('std::tr1::', 'unordered_map', 866 Tr1UnorderedMapPrinter) 867 libstdcxx_printer.add_version('std::tr1::', 'unordered_set', 868 Tr1UnorderedSetPrinter) 869 libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap', 870 Tr1UnorderedMapPrinter) 871 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset', 872 Tr1UnorderedSetPrinter) 873 874 # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. 875 # The tr1 namespace printers do not seem to have any debug 876 # equivalents, so do no register them. 877 libstdcxx_printer.add('std::__debug::unordered_map', 878 Tr1UnorderedMapPrinter) 879 libstdcxx_printer.add('std::__debug::unordered_set', 880 Tr1UnorderedSetPrinter) 881 libstdcxx_printer.add('std::__debug::unordered_multimap', 882 Tr1UnorderedMapPrinter) 883 libstdcxx_printer.add('std::__debug::unordered_multiset', 884 Tr1UnorderedSetPrinter) 885 libstdcxx_printer.add('std::__debug::forward_list', 886 StdForwardListPrinter) 887 888 889 # Extensions. 890 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) 891 892 if True: 893 # These shouldn't be necessary, if GDB "print *i" worked. 894 # But it often doesn't, so here they are. 895 libstdcxx_printer.add_container('std::', '_List_iterator', 896 StdListIteratorPrinter) 897 libstdcxx_printer.add_container('std::', '_List_const_iterator', 898 StdListIteratorPrinter) 899 libstdcxx_printer.add_version('std::', '_Rb_tree_iterator', 900 StdRbtreeIteratorPrinter) 901 libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator', 902 StdRbtreeIteratorPrinter) 903 libstdcxx_printer.add_container('std::', '_Deque_iterator', 904 StdDequeIteratorPrinter) 905 libstdcxx_printer.add_container('std::', '_Deque_const_iterator', 906 StdDequeIteratorPrinter) 907 libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator', 908 StdVectorIteratorPrinter) 909 libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator', 910 StdSlistIteratorPrinter) 911 912 # Debug (compiled with -D_GLIBCXX_DEBUG) printer 913 # registrations. The Rb_tree debug iterator when unwrapped 914 # from the encapsulating __gnu_debug::_Safe_iterator does not 915 # have the __norm namespace. Just use the existing printer 916 # registration for that. 917 libstdcxx_printer.add('__gnu_debug::_Safe_iterator', 918 StdDebugIteratorPrinter) 919 libstdcxx_printer.add('std::__norm::_List_iterator', 920 StdListIteratorPrinter) 921 libstdcxx_printer.add('std::__norm::_List_const_iterator', 922 StdListIteratorPrinter) 923 libstdcxx_printer.add('std::__norm::_Deque_const_iterator', 924 StdDequeIteratorPrinter) 925 libstdcxx_printer.add('std::__norm::_Deque_iterator', 926 StdDequeIteratorPrinter) 927 928 build_libstdcxx_dictionary () 929