xref: /openbsd-src/gnu/llvm/libcxx/utils/gdb/libcxx/printers.py (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1#===----------------------------------------------------------------------===##
2#
3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4# See https://llvm.org/LICENSE.txt for license information.
5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#
7#===----------------------------------------------------------------------===##
8"""GDB pretty-printers for libc++.
9
10These should work for objects compiled with either the stable ABI or the unstable ABI.
11"""
12
13from __future__ import print_function
14
15import math
16import re
17import gdb
18
19# One under-documented feature of the gdb pretty-printer API
20# is that clients can call any other member of the API
21# before they call to_string.
22# Therefore all self.FIELDs must be set in the pretty-printer's
23# __init__ function.
24
25_void_pointer_type = gdb.lookup_type("void").pointer()
26
27
28_long_int_type = gdb.lookup_type("unsigned long long")
29
30_libcpp_big_endian = False
31
32def addr_as_long(addr):
33    return int(addr.cast(_long_int_type))
34
35
36# The size of a pointer in bytes.
37_pointer_size = _void_pointer_type.sizeof
38
39
40def _remove_cxx_namespace(typename):
41    """Removed libc++ specific namespace from the type.
42
43    Arguments:
44      typename(string): A type, such as std::__u::something.
45
46    Returns:
47      A string without the libc++ specific part, such as std::something.
48    """
49
50    return re.sub("std::__.*?::", "std::", typename)
51
52
53def _remove_generics(typename):
54    """Remove generics part of the type. Assumes typename is not empty.
55
56    Arguments:
57      typename(string): A type such as std::my_collection<element>.
58
59    Returns:
60      The prefix up to the generic part, such as std::my_collection.
61    """
62
63    match = re.match("^([^<]+)", typename)
64    return match.group(1)
65
66
67def _cc_field(node):
68    """Previous versions of libcxx had inconsistent field naming naming. Handle
69    both types.
70    """
71    try:
72        return node["__value_"]["__cc_"]
73    except:
74        return node["__value_"]["__cc"]
75
76
77def _data_field(node):
78    """Previous versions of libcxx had inconsistent field naming naming. Handle
79    both types.
80    """
81    try:
82        return node["__data_"]
83    except:
84        return node["__data"]
85
86
87def _size_field(node):
88    """Previous versions of libcxx had inconsistent field naming naming. Handle
89    both types.
90    """
91    try:
92        return node["__size_"]
93    except:
94        return node["__size"]
95
96
97# Some common substitutions on the types to reduce visual clutter (A user who
98# wants to see the actual details can always use print/r).
99_common_substitutions = [
100    ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
101     "std::string"),
102    ("std::basic_string_view<char, std::char_traits<char> >",
103     "std::string_view"),
104]
105
106
107def _prettify_typename(gdb_type):
108    """Returns a pretty name for the type, or None if no name can be found.
109
110    Arguments:
111      gdb_type(gdb.Type): A type object.
112
113    Returns:
114      A string, without type_defs, libc++ namespaces, and common substitutions
115      applied.
116    """
117
118    type_without_typedefs = gdb_type.strip_typedefs()
119    typename = type_without_typedefs.name or type_without_typedefs.tag or \
120        str(type_without_typedefs)
121    result = _remove_cxx_namespace(typename)
122    for find_str, subst_str in _common_substitutions:
123        result = re.sub(find_str, subst_str, result)
124    return result
125
126
127def _typename_for_nth_generic_argument(gdb_type, n):
128    """Returns a pretty string for the nth argument of the given type.
129
130    Arguments:
131      gdb_type(gdb.Type): A type object, such as the one for std::map<int, int>
132      n: The (zero indexed) index of the argument to return.
133
134    Returns:
135      A string for the nth argument, such a "std::string"
136    """
137    element_type = gdb_type.template_argument(n)
138    return _prettify_typename(element_type)
139
140
141def _typename_with_n_generic_arguments(gdb_type, n):
142    """Return a string for the type with the first n (1, ...) generic args."""
143
144    base_type = _remove_generics(_prettify_typename(gdb_type))
145    arg_list = [base_type]
146    template = "%s<"
147    for i in range(n):
148        arg_list.append(_typename_for_nth_generic_argument(gdb_type, i))
149        template += "%s, "
150    result = (template[:-2] + ">") % tuple(arg_list)
151    return result
152
153
154def _typename_with_first_generic_argument(gdb_type):
155    return _typename_with_n_generic_arguments(gdb_type, 1)
156
157
158class StdTuplePrinter(object):
159    """Print a std::tuple."""
160
161    class _Children(object):
162        """Class to iterate over the tuple's children."""
163
164        def __init__(self, val):
165            self.val = val
166            self.child_iter = iter(self.val["__base_"].type.fields())
167            self.count = 0
168
169        def __iter__(self):
170            return self
171
172        def __next__(self):
173            # child_iter raises StopIteration when appropriate.
174            field_name = next(self.child_iter)
175            child = self.val["__base_"][field_name]["__value_"]
176            self.count += 1
177            return ("[%d]" % self.count, child)
178
179        next = __next__  # Needed for GDB built against Python 2.7.
180
181    def __init__(self, val):
182        self.val = val
183
184    def to_string(self):
185        typename = _remove_generics(_prettify_typename(self.val.type))
186        if not self.val.type.fields():
187            return "empty %s" % typename
188        return "%s containing" % typename
189
190    def children(self):
191        if not self.val.type.fields():
192            return iter(())
193        return self._Children(self.val)
194
195
196def _get_base_subobject(child_class_value, index=0):
197    """Returns the object's value in the form of the parent class at index.
198
199    This function effectively casts the child_class_value to the base_class's
200    type, but the type-to-cast to is stored in the field at index, and once
201    we know the field, we can just return the data.
202
203    Args:
204      child_class_value: the value to cast
205      index: the parent class index
206
207    Raises:
208      Exception: field at index was not a base-class field.
209    """
210
211    field = child_class_value.type.fields()[index]
212    if not field.is_base_class:
213        raise Exception("Not a base-class field.")
214    return child_class_value[field]
215
216
217def _value_of_pair_first(value):
218    """Convenience for _get_base_subobject, for the common case."""
219    return _get_base_subobject(value, 0)["__value_"]
220
221
222class StdStringPrinter(object):
223    """Print a std::string."""
224
225    def __init__(self, val):
226        self.val = val
227
228    def to_string(self):
229        """Build a python string from the data whether stored inline or separately."""
230        value_field = _value_of_pair_first(self.val["__r_"])
231        short_field = value_field["__s"]
232        short_size = short_field["__size_"]
233        if short_field["__is_long_"]:
234            long_field = value_field["__l"]
235            data = long_field["__data_"]
236            size = long_field["__size_"]
237        else:
238            data = short_field["__data_"]
239            size = short_field["__size_"]
240        return data.lazy_string(length=size)
241
242    def display_hint(self):
243        return "string"
244
245
246class StdStringViewPrinter(object):
247    """Print a std::string_view."""
248
249    def __init__(self, val):
250      self.val = val
251
252    def display_hint(self):
253      return "string"
254
255    def to_string(self):  # pylint: disable=g-bad-name
256      """GDB calls this to compute the pretty-printed form."""
257
258      ptr = _data_field(self.val)
259      ptr = ptr.cast(ptr.type.target().strip_typedefs().pointer())
260      size = _size_field(self.val)
261      return ptr.lazy_string(length=size)
262
263
264class StdUniquePtrPrinter(object):
265    """Print a std::unique_ptr."""
266
267    def __init__(self, val):
268        self.val = val
269        self.addr = _value_of_pair_first(self.val["__ptr_"])
270        self.pointee_type = self.val.type.template_argument(0)
271
272    def to_string(self):
273        typename = _remove_generics(_prettify_typename(self.val.type))
274        if not self.addr:
275            return "%s is nullptr" % typename
276        return ("%s<%s> containing" %
277                (typename,
278                 _remove_generics(_prettify_typename(self.pointee_type))))
279
280    def __iter__(self):
281        if self.addr:
282            yield "__ptr_", self.addr.cast(self.pointee_type.pointer())
283
284    def children(self):
285        return self
286
287
288class StdSharedPointerPrinter(object):
289    """Print a std::shared_ptr."""
290
291    def __init__(self, val):
292        self.val = val
293        self.addr = self.val["__ptr_"]
294
295    def to_string(self):
296        """Returns self as a string."""
297        typename = _remove_generics(_prettify_typename(self.val.type))
298        pointee_type = _remove_generics(
299            _prettify_typename(self.val.type.template_argument(0)))
300        if not self.addr:
301            return "%s is nullptr" % typename
302        refcount = self.val["__cntrl_"]
303        if refcount != 0:
304            try:
305                usecount = refcount["__shared_owners_"] + 1
306                weakcount = refcount["__shared_weak_owners_"]
307                if usecount == 0:
308                    state = "expired, weak %d" % weakcount
309                else:
310                    state = "count %d, weak %d" % (usecount, weakcount)
311            except:
312                # Debug info for a class with virtual functions is emitted
313                # in the same place as its key function. That means that
314                # for std::shared_ptr, __shared_owners_ is emitted into
315                # into libcxx.[so|a] itself, rather than into the shared_ptr
316                # instantiation point. So if libcxx.so was built without
317                # debug info, these fields will be missing.
318                state = "count ?, weak ? (libc++ missing debug info)"
319        return "%s<%s> %s containing" % (typename, pointee_type, state)
320
321    def __iter__(self):
322        if self.addr:
323            yield "__ptr_", self.addr
324
325    def children(self):
326        return self
327
328
329class StdVectorPrinter(object):
330    """Print a std::vector."""
331
332    class _VectorBoolIterator(object):
333        """Class to iterate over the bool vector's children."""
334
335        def __init__(self, begin, size, bits_per_word):
336            self.item = begin
337            self.size = size
338            self.bits_per_word = bits_per_word
339            self.count = 0
340            self.offset = 0
341
342        def __iter__(self):
343            return self
344
345        def __next__(self):
346            """Retrieve the next element."""
347
348            self.count += 1
349            if self.count > self.size:
350                raise StopIteration
351            entry = self.item.dereference()
352            if entry & (1 << self.offset):
353                outbit = 1
354            else:
355                outbit = 0
356            self.offset += 1
357            if self.offset >= self.bits_per_word:
358                self.item += 1
359                self.offset = 0
360            return ("[%d]" % self.count, outbit)
361
362        next = __next__  # Needed for GDB built against Python 2.7.
363
364    class _VectorIterator(object):
365        """Class to iterate over the non-bool vector's children."""
366
367        def __init__(self, begin, end):
368            self.item = begin
369            self.end = end
370            self.count = 0
371
372        def __iter__(self):
373            return self
374
375        def __next__(self):
376            self.count += 1
377            if self.item == self.end:
378                raise StopIteration
379            entry = self.item.dereference()
380            self.item += 1
381            return ("[%d]" % self.count, entry)
382
383        next = __next__  # Needed for GDB built against Python 2.7.
384
385    def __init__(self, val):
386        """Set val, length, capacity, and iterator for bool and normal vectors."""
387        self.val = val
388        self.typename = _remove_generics(_prettify_typename(val.type))
389        begin = self.val["__begin_"]
390        if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
391            self.typename += "<bool>"
392            self.length = self.val["__size_"]
393            bits_per_word = self.val["__bits_per_word"]
394            self.capacity = _value_of_pair_first(
395                self.val["__cap_alloc_"]) * bits_per_word
396            self.iterator = self._VectorBoolIterator(
397                begin, self.length, bits_per_word)
398        else:
399            end = self.val["__end_"]
400            self.length = end - begin
401            self.capacity = _get_base_subobject(
402                self.val["__end_cap_"])["__value_"] - begin
403            self.iterator = self._VectorIterator(begin, end)
404
405    def to_string(self):
406        return ("%s of length %d, capacity %d" %
407                (self.typename, self.length, self.capacity))
408
409    def children(self):
410        return self.iterator
411
412    def display_hint(self):
413        return "array"
414
415
416class StdBitsetPrinter(object):
417    """Print a std::bitset."""
418
419    def __init__(self, val):
420        self.val = val
421        self.n_words = int(self.val["__n_words"])
422        self.bits_per_word = int(self.val["__bits_per_word"])
423        self.bit_count = self.val.type.template_argument(0)
424        if self.n_words == 1:
425            self.values = [int(self.val["__first_"])]
426        else:
427            self.values = [int(self.val["__first_"][index])
428                           for index in range(self.n_words)]
429
430    def to_string(self):
431        typename = _prettify_typename(self.val.type)
432        return "%s" % typename
433
434    def _list_it(self):
435        for bit in range(self.bit_count):
436            word = bit // self.bits_per_word
437            word_bit = bit % self.bits_per_word
438            if self.values[word] & (1 << word_bit):
439                yield ("[%d]" % bit, 1)
440
441    def __iter__(self):
442        return self._list_it()
443
444    def children(self):
445        return self
446
447
448class StdDequePrinter(object):
449    """Print a std::deque."""
450
451    def __init__(self, val):
452        self.val = val
453        self.size = int(_value_of_pair_first(val["__size_"]))
454        self.start_ptr = self.val["__map_"]["__begin_"]
455        self.first_block_start_index = int(self.val["__start_"])
456        self.node_type = self.start_ptr.type
457        self.block_size = self._calculate_block_size(
458            val.type.template_argument(0))
459
460    def _calculate_block_size(self, element_type):
461        """Calculates the number of elements in a full block."""
462        size = element_type.sizeof
463        # Copied from struct __deque_block_size implementation of libcxx.
464        return 4096 / size if size < 256 else 16
465
466    def _bucket_it(self, start_addr, start_index, end_index):
467        for i in range(start_index, end_index):
468            yield i, (start_addr.dereference() + i).dereference()
469
470    def _list_it(self):
471        """Primary iteration worker."""
472        num_emitted = 0
473        current_addr = self.start_ptr
474        start_index = self.first_block_start_index
475        while num_emitted < self.size:
476            end_index = min(start_index + self.size -
477                            num_emitted, self.block_size)
478            for _, elem in self._bucket_it(current_addr, start_index, end_index):
479                yield "", elem
480            num_emitted += end_index - start_index
481            current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size) \
482                              .cast(self.node_type)
483            start_index = 0
484
485    def to_string(self):
486        typename = _remove_generics(_prettify_typename(self.val.type))
487        if self.size:
488            return "%s with %d elements" % (typename, self.size)
489        return "%s is empty" % typename
490
491    def __iter__(self):
492        return self._list_it()
493
494    def children(self):
495        return self
496
497    def display_hint(self):
498        return "array"
499
500
501class StdListPrinter(object):
502    """Print a std::list."""
503
504    def __init__(self, val):
505        self.val = val
506        size_alloc_field = self.val["__size_alloc_"]
507        self.size = int(_value_of_pair_first(size_alloc_field))
508        dummy_node = self.val["__end_"]
509        self.nodetype = gdb.lookup_type(
510            re.sub("__list_node_base", "__list_node",
511                   str(dummy_node.type.strip_typedefs()))).pointer()
512        self.first_node = dummy_node["__next_"]
513
514    def to_string(self):
515        typename = _remove_generics(_prettify_typename(self.val.type))
516        if self.size:
517            return "%s with %d elements" % (typename, self.size)
518        return "%s is empty" % typename
519
520    def _list_iter(self):
521        current_node = self.first_node
522        for _ in range(self.size):
523            yield "", current_node.cast(self.nodetype).dereference()["__value_"]
524            current_node = current_node.dereference()["__next_"]
525
526    def __iter__(self):
527        return self._list_iter()
528
529    def children(self):
530        return self if self.nodetype else iter(())
531
532    def display_hint(self):
533        return "array"
534
535
536class StdQueueOrStackPrinter(object):
537    """Print a std::queue or std::stack."""
538
539    def __init__(self, val):
540        self.val = val
541        self.underlying = val["c"]
542
543    def to_string(self):
544        typename = _remove_generics(_prettify_typename(self.val.type))
545        return "%s wrapping" % typename
546
547    def children(self):
548        return iter([("", self.underlying)])
549
550    def display_hint(self):
551        return "array"
552
553
554class StdPriorityQueuePrinter(object):
555    """Print a std::priority_queue."""
556
557    def __init__(self, val):
558        self.val = val
559        self.underlying = val["c"]
560
561    def to_string(self):
562        # TODO(tamur): It would be nice to print the top element. The technical
563        # difficulty is that, the implementation refers to the underlying
564        # container, which is a generic class. libstdcxx pretty printers do not
565        # print the top element.
566        typename = _remove_generics(_prettify_typename(self.val.type))
567        return "%s wrapping" % typename
568
569    def children(self):
570        return iter([("", self.underlying)])
571
572    def display_hint(self):
573        return "array"
574
575
576class RBTreeUtils(object):
577    """Utility class for std::(multi)map, and std::(multi)set and iterators."""
578
579    def __init__(self, cast_type, root):
580        self.cast_type = cast_type
581        self.root = root
582
583    def left_child(self, node):
584        result = node.cast(self.cast_type).dereference()["__left_"]
585        return result
586
587    def right_child(self, node):
588        result = node.cast(self.cast_type).dereference()["__right_"]
589        return result
590
591    def parent(self, node):
592        """Return the parent of node, if it exists."""
593        # If this is the root, then from the algorithm's point of view, it has no
594        # parent.
595        if node == self.root:
596            return None
597
598        # We don't have enough information to tell if this is the end_node (which
599        # doesn't have a __parent_ field), or the root (which doesn't have a parent
600        # from the algorithm's point of view), so cast_type may not be correct for
601        # this particular node. Use heuristics.
602
603        # The end_node's left child is the root. Note that when printing interators
604        # in isolation, the root is unknown.
605        if self.left_child(node) == self.root:
606            return None
607
608        parent = node.cast(self.cast_type).dereference()["__parent_"]
609        # If the value at the offset of __parent_ doesn't look like a valid pointer,
610        # then assume that node is the end_node (and therefore has no parent).
611        # End_node type has a pointer embedded, so should have pointer alignment.
612        if addr_as_long(parent) % _void_pointer_type.alignof:
613            return None
614        # This is ugly, but the only other option is to dereference an invalid
615        # pointer.  0x8000 is fairly arbitrary, but has had good results in
616        # practice.  If there was a way to tell if a pointer is invalid without
617        # actually dereferencing it and spewing error messages, that would be ideal.
618        if parent < 0x8000:
619            return None
620        return parent
621
622    def is_left_child(self, node):
623        parent = self.parent(node)
624        return parent is not None and self.left_child(parent) == node
625
626    def is_right_child(self, node):
627        parent = self.parent(node)
628        return parent is not None and self.right_child(parent) == node
629
630
631class AbstractRBTreePrinter(object):
632    """Abstract super class for std::(multi)map, and std::(multi)set."""
633
634    def __init__(self, val):
635        self.val = val
636        tree = self.val["__tree_"]
637        self.size = int(_value_of_pair_first(tree["__pair3_"]))
638        dummy_root = tree["__pair1_"]
639        root = _value_of_pair_first(dummy_root)["__left_"]
640        cast_type = self._init_cast_type(val.type)
641        self.util = RBTreeUtils(cast_type, root)
642
643    def _get_key_value(self, node):
644        """Subclasses should override to return a list of values to yield."""
645        raise NotImplementedError
646
647    def _traverse(self):
648        """Traverses the binary search tree in order."""
649        current = self.util.root
650        skip_left_child = False
651        while True:
652            if not skip_left_child and self.util.left_child(current):
653                current = self.util.left_child(current)
654                continue
655            skip_left_child = False
656            for key_value in self._get_key_value(current):
657                yield "", key_value
658            right_child = self.util.right_child(current)
659            if right_child:
660                current = right_child
661                continue
662            while self.util.is_right_child(current):
663                current = self.util.parent(current)
664            if self.util.is_left_child(current):
665                current = self.util.parent(current)
666                skip_left_child = True
667                continue
668            break
669
670    def __iter__(self):
671        return self._traverse()
672
673    def children(self):
674        return self if self.util.cast_type and self.size > 0 else iter(())
675
676    def to_string(self):
677        typename = _remove_generics(_prettify_typename(self.val.type))
678        if self.size:
679            return "%s with %d elements" % (typename, self.size)
680        return "%s is empty" % typename
681
682
683class StdMapPrinter(AbstractRBTreePrinter):
684    """Print a std::map or std::multimap."""
685
686    def _init_cast_type(self, val_type):
687        map_it_type = gdb.lookup_type(
688            str(val_type.strip_typedefs()) + "::iterator").strip_typedefs()
689        tree_it_type = map_it_type.template_argument(0)
690        node_ptr_type = tree_it_type.template_argument(1)
691        return node_ptr_type
692
693    def display_hint(self):
694        return "map"
695
696    def _get_key_value(self, node):
697        key_value = _cc_field(node.cast(self.util.cast_type).dereference())
698        return [key_value["first"], key_value["second"]]
699
700
701class StdSetPrinter(AbstractRBTreePrinter):
702    """Print a std::set."""
703
704    def _init_cast_type(self, val_type):
705        set_it_type = gdb.lookup_type(
706            str(val_type.strip_typedefs()) + "::iterator").strip_typedefs()
707        node_ptr_type = set_it_type.template_argument(1)
708        return node_ptr_type
709
710    def display_hint(self):
711        return "array"
712
713    def _get_key_value(self, node):
714        key_value = node.cast(self.util.cast_type).dereference()["__value_"]
715        return [key_value]
716
717
718class AbstractRBTreeIteratorPrinter(object):
719    """Abstract super class for std::(multi)map, and std::(multi)set iterator."""
720
721    def _initialize(self, val, typename):
722        self.typename = typename
723        self.val = val
724        self.addr = self.val["__ptr_"]
725        cast_type = self.val.type.template_argument(1)
726        self.util = RBTreeUtils(cast_type, None)
727        if self.addr:
728            self.node = self.addr.cast(cast_type).dereference()
729
730    def _is_valid_node(self):
731        if not self.util.parent(self.addr):
732            return False
733        return self.util.is_left_child(self.addr) or \
734            self.util.is_right_child(self.addr)
735
736    def to_string(self):
737        if not self.addr:
738            return "%s is nullptr" % self.typename
739        return "%s " % self.typename
740
741    def _get_node_value(self, node):
742        raise NotImplementedError
743
744    def __iter__(self):
745        addr_str = "[%s]" % str(self.addr)
746        if not self._is_valid_node():
747            yield addr_str, " end()"
748        else:
749            yield addr_str, self._get_node_value(self.node)
750
751    def children(self):
752        return self if self.addr else iter(())
753
754
755class MapIteratorPrinter(AbstractRBTreeIteratorPrinter):
756    """Print a std::(multi)map iterator."""
757
758    def __init__(self, val):
759        self._initialize(val["__i_"],
760                         _remove_generics(_prettify_typename(val.type)))
761
762    def _get_node_value(self, node):
763        return _cc_field(node)
764
765
766class SetIteratorPrinter(AbstractRBTreeIteratorPrinter):
767    """Print a std::(multi)set iterator."""
768
769    def __init__(self, val):
770        self._initialize(val, _remove_generics(_prettify_typename(val.type)))
771
772    def _get_node_value(self, node):
773        return node["__value_"]
774
775
776class StdFposPrinter(object):
777    """Print a std::fpos or std::streampos."""
778
779    def __init__(self, val):
780        self.val = val
781
782    def to_string(self):
783        typename = _remove_generics(_prettify_typename(self.val.type))
784        offset = self.val["__off_"]
785        state = self.val["__st_"]
786
787        state_fields = []
788        if state.type.code == gdb.TYPE_CODE_STRUCT:
789            state_fields = [f.name for f in state.type.fields()]
790
791        state_string = ""
792        if "__count" in state_fields and "__value" in state_fields:
793            count = state["__count"]
794            value = state["__value"]["__wch"]
795            state_string = " with state: {count:%s value:%s}" % (count, value)
796
797        return "%s with stream offset:%s%s" % (typename, offset, state_string)
798
799
800class AbstractUnorderedCollectionPrinter(object):
801    """Abstract super class for std::unordered_(multi)[set|map]."""
802
803    def __init__(self, val):
804        self.val = val
805        self.table = val["__table_"]
806        self.sentinel = self.table["__p1_"]
807        self.size = int(_value_of_pair_first(self.table["__p2_"]))
808        node_base_type = self.sentinel.type.template_argument(0)
809        self.cast_type = node_base_type.template_argument(0)
810
811    def _list_it(self, sentinel_ptr):
812        next_ptr = _value_of_pair_first(sentinel_ptr)["__next_"]
813        while str(next_ptr.cast(_void_pointer_type)) != "0x0":
814            next_val = next_ptr.cast(self.cast_type).dereference()
815            for key_value in self._get_key_value(next_val):
816                yield "", key_value
817            next_ptr = next_val["__next_"]
818
819    def to_string(self):
820        typename = _remove_generics(_prettify_typename(self.val.type))
821        if self.size:
822            return "%s with %d elements" % (typename, self.size)
823        return "%s is empty" % typename
824
825    def _get_key_value(self, node):
826        """Subclasses should override to return a list of values to yield."""
827        raise NotImplementedError
828
829    def children(self):
830        return self if self.cast_type and self.size > 0 else iter(())
831
832    def __iter__(self):
833        return self._list_it(self.sentinel)
834
835
836class StdUnorderedSetPrinter(AbstractUnorderedCollectionPrinter):
837    """Print a std::unordered_(multi)set."""
838
839    def _get_key_value(self, node):
840        return [node["__value_"]]
841
842    def display_hint(self):
843        return "array"
844
845
846class StdUnorderedMapPrinter(AbstractUnorderedCollectionPrinter):
847    """Print a std::unordered_(multi)map."""
848
849    def _get_key_value(self, node):
850        key_value = _cc_field(node)
851        return [key_value["first"], key_value["second"]]
852
853    def display_hint(self):
854        return "map"
855
856
857class AbstractHashMapIteratorPrinter(object):
858    """Abstract class for unordered collection iterators."""
859
860    def _initialize(self, val, addr):
861        self.val = val
862        self.typename = _remove_generics(_prettify_typename(self.val.type))
863        self.addr = addr
864        if self.addr:
865            self.node = self.addr.cast(self.cast_type).dereference()
866
867    def _get_key_value(self):
868        """Subclasses should override to return a list of values to yield."""
869        raise NotImplementedError
870
871    def to_string(self):
872        if not self.addr:
873            return "%s = end()" % self.typename
874        return "%s " % self.typename
875
876    def children(self):
877        return self if self.addr else iter(())
878
879    def __iter__(self):
880        for key_value in self._get_key_value():
881            yield "", key_value
882
883
884class StdUnorderedSetIteratorPrinter(AbstractHashMapIteratorPrinter):
885    """Print a std::(multi)set iterator."""
886
887    def __init__(self, val):
888        self.cast_type = val.type.template_argument(0)
889        self._initialize(val, val["__node_"])
890
891    def _get_key_value(self):
892        return [self.node["__value_"]]
893
894    def display_hint(self):
895        return "array"
896
897
898class StdUnorderedMapIteratorPrinter(AbstractHashMapIteratorPrinter):
899    """Print a std::(multi)map iterator."""
900
901    def __init__(self, val):
902        self.cast_type = val.type.template_argument(0).template_argument(0)
903        self._initialize(val, val["__i_"]["__node_"])
904
905    def _get_key_value(self):
906        key_value = _cc_field(self.node)
907        return [key_value["first"], key_value["second"]]
908
909    def display_hint(self):
910        return "map"
911
912
913def _remove_std_prefix(typename):
914    match = re.match("^std::(.+)", typename)
915    return match.group(1) if match is not None else ""
916
917
918class LibcxxPrettyPrinter(object):
919    """PrettyPrinter object so gdb-commands like 'info pretty-printers' work."""
920
921    def __init__(self, name):
922        super(LibcxxPrettyPrinter, self).__init__()
923        self.name = name
924        self.enabled = True
925
926        self.lookup = {
927            "basic_string": StdStringPrinter,
928            "string": StdStringPrinter,
929            "string_view": StdStringViewPrinter,
930            "tuple": StdTuplePrinter,
931            "unique_ptr": StdUniquePtrPrinter,
932            "shared_ptr": StdSharedPointerPrinter,
933            "weak_ptr": StdSharedPointerPrinter,
934            "bitset": StdBitsetPrinter,
935            "deque": StdDequePrinter,
936            "list": StdListPrinter,
937            "queue": StdQueueOrStackPrinter,
938            "stack": StdQueueOrStackPrinter,
939            "priority_queue": StdPriorityQueuePrinter,
940            "map": StdMapPrinter,
941            "multimap": StdMapPrinter,
942            "set": StdSetPrinter,
943            "multiset": StdSetPrinter,
944            "vector": StdVectorPrinter,
945            "__map_iterator": MapIteratorPrinter,
946            "__map_const_iterator": MapIteratorPrinter,
947            "__tree_iterator": SetIteratorPrinter,
948            "__tree_const_iterator": SetIteratorPrinter,
949            "fpos": StdFposPrinter,
950            "unordered_set": StdUnorderedSetPrinter,
951            "unordered_multiset": StdUnorderedSetPrinter,
952            "unordered_map": StdUnorderedMapPrinter,
953            "unordered_multimap": StdUnorderedMapPrinter,
954            "__hash_map_iterator": StdUnorderedMapIteratorPrinter,
955            "__hash_map_const_iterator": StdUnorderedMapIteratorPrinter,
956            "__hash_iterator": StdUnorderedSetIteratorPrinter,
957            "__hash_const_iterator": StdUnorderedSetIteratorPrinter,
958        }
959
960        self.subprinters = []
961        for name, subprinter in self.lookup.items():
962            # Subprinters and names are used only for the rarely used command "info
963            # pretty" (and related), so the name of the first data structure it prints
964            # is a reasonable choice.
965            if subprinter not in self.subprinters:
966                subprinter.name = name
967                self.subprinters.append(subprinter)
968
969    def __call__(self, val):
970        """Return the pretty printer for a val, if the type is supported."""
971
972        # Do not handle any type that is not a struct/class.
973        if val.type.strip_typedefs().code != gdb.TYPE_CODE_STRUCT:
974            return None
975
976        # Don't attempt types known to be inside libstdcxx.
977        typename = val.type.name or val.type.tag or str(val.type)
978        match = re.match("^std::(__.*?)::", typename)
979        if match is not None and match.group(1) in ["__cxx1998",
980                                                    "__debug",
981                                                    "__7",
982                                                    "__g"]:
983            return None
984
985        # Handle any using declarations or other typedefs.
986        typename = _prettify_typename(val.type)
987        if not typename:
988            return None
989        without_generics = _remove_generics(typename)
990        lookup_name = _remove_std_prefix(without_generics)
991        if lookup_name in self.lookup:
992            return self.lookup[lookup_name](val)
993        return None
994
995
996_libcxx_printer_name = "libcxx_pretty_printer"
997
998
999# These are called for every binary object file, which could be thousands in
1000# certain pathological cases. Limit our pretty printers to the progspace.
1001def _register_libcxx_printers(event):
1002    progspace = event.new_objfile.progspace
1003    # It would be ideal to get the endianness at print time, but
1004    # gdb.execute clears gdb's internal wrap buffer, removing any values
1005    # already generated as part of a larger data structure, and there is
1006    # no python api to get the endianness. Mixed-endianness debugging
1007    # rare enough that this workaround should be adequate.
1008    _libcpp_big_endian = "big endian" in gdb.execute("show endian",
1009                                                     to_string=True)
1010
1011    if not getattr(progspace, _libcxx_printer_name, False):
1012        print("Loading libc++ pretty-printers.")
1013        gdb.printing.register_pretty_printer(
1014            progspace, LibcxxPrettyPrinter(_libcxx_printer_name))
1015        setattr(progspace, _libcxx_printer_name, True)
1016
1017
1018def _unregister_libcxx_printers(event):
1019    progspace = event.progspace
1020    if getattr(progspace, _libcxx_printer_name, False):
1021        for printer in progspace.pretty_printers:
1022            if getattr(printer, "name", "none") == _libcxx_printer_name:
1023                progspace.pretty_printers.remove(printer)
1024                setattr(progspace, _libcxx_printer_name, False)
1025                break
1026
1027
1028def register_libcxx_printer_loader():
1029    """Register event handlers to load libc++ pretty-printers."""
1030    gdb.events.new_objfile.connect(_register_libcxx_printers)
1031    gdb.events.clear_objfiles.connect(_unregister_libcxx_printers)
1032