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