xref: /aosp_15_r20/prebuilts/rust/linux-musl-x86/1.80.1/lib/rustlib/etc/gdb_lookup.py (revision b40554a23088fb75aa6945dfe8e65169c8484da3)
1import gdb
2import gdb.printing
3import re
4
5from gdb_providers import *
6from rust_types import *
7
8
9_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
10gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
11
12def register_printers(objfile):
13    objfile.pretty_printers.append(printer)
14
15
16# BACKCOMPAT: rust 1.35
17def is_hashbrown_hashmap(hash_map):
18    return len(hash_map.type.fields()) == 1
19
20
21def classify_rust_type(type):
22    type_class = type.code
23    if type_class == gdb.TYPE_CODE_STRUCT:
24        return classify_struct(type.tag, type.fields())
25    if type_class == gdb.TYPE_CODE_UNION:
26        return classify_union(type.fields())
27
28    return RustType.OTHER
29
30
31def check_enum_discriminant(valobj):
32    content = valobj[valobj.type.fields()[0]]
33    fields = content.type.fields()
34    if len(fields) > 1:
35        discriminant = int(content[fields[0]]) + 1
36        if discriminant > len(fields):
37            # invalid discriminant
38            return False
39    return True
40
41
42# Helper for enum printing that checks the discriminant.  Only used in
43# older gdb.
44def enum_provider(valobj):
45    if check_enum_discriminant(valobj):
46        return EnumProvider(valobj)
47    return None
48
49
50# Helper to handle both old and new hash maps.
51def hashmap_provider(valobj):
52    if is_hashbrown_hashmap(valobj):
53        return StdHashMapProvider(valobj)
54    else:
55        return StdOldHashMapProvider(valobj)
56
57
58# Helper to handle both old and new hash sets.
59def hashset_provider(valobj):
60    hash_map = valobj[valobj.type.fields()[0]]
61    if is_hashbrown_hashmap(hash_map):
62        return StdHashMapProvider(valobj, show_values=False)
63    else:
64        return StdOldHashMapProvider(hash_map, show_values=False)
65
66
67class PrintByRustType(gdb.printing.SubPrettyPrinter):
68    def __init__(self, name, provider):
69        super(PrintByRustType, self).__init__(name)
70        self.provider = provider
71
72    def __call__(self, val):
73        if self.enabled:
74            return self.provider(val)
75        return None
76
77
78class RustPrettyPrinter(gdb.printing.PrettyPrinter):
79    def __init__(self, name):
80        super(RustPrettyPrinter, self).__init__(name, [])
81        self.type_map = {}
82
83    def add(self, rust_type, provider):
84        # Just use the rust_type as the name.
85        printer = PrintByRustType(rust_type, provider)
86        self.type_map[rust_type] = printer
87        self.subprinters.append(printer)
88
89    def __call__(self, valobj):
90        rust_type = classify_rust_type(valobj.type)
91        if rust_type in self.type_map:
92            return self.type_map[rust_type](valobj)
93        return None
94
95
96printer = RustPrettyPrinter("rust")
97# use enum provider only for GDB <7.12
98if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12):
99    printer.add(RustType.ENUM, enum_provider)
100printer.add(RustType.STD_STRING, StdStringProvider)
101printer.add(RustType.STD_OS_STRING, StdOsStringProvider)
102printer.add(RustType.STD_STR, StdStrProvider)
103printer.add(RustType.STD_SLICE, StdSliceProvider)
104printer.add(RustType.STD_VEC, StdVecProvider)
105printer.add(RustType.STD_VEC_DEQUE, StdVecDequeProvider)
106printer.add(RustType.STD_BTREE_SET, StdBTreeSetProvider)
107printer.add(RustType.STD_BTREE_MAP, StdBTreeMapProvider)
108printer.add(RustType.STD_HASH_MAP, hashmap_provider)
109printer.add(RustType.STD_HASH_SET, hashset_provider)
110printer.add(RustType.STD_RC, StdRcProvider)
111printer.add(RustType.STD_ARC, lambda valobj: StdRcProvider(valobj, is_atomic=True))
112
113printer.add(RustType.STD_CELL, StdCellProvider)
114printer.add(RustType.STD_REF, StdRefProvider)
115printer.add(RustType.STD_REF_MUT, StdRefProvider)
116printer.add(RustType.STD_REF_CELL, StdRefCellProvider)
117
118printer.add(RustType.STD_NONZERO_NUMBER, StdNonZeroNumberProvider)
119