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