1
+ # Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2
+ # file at the top-level directory of this distribution and at
3
+ # http://rust-lang.org/COPYRIGHT.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6
+ # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7
+ # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
+ # option. This file may not be copied, modified, or distributed
9
+ # except according to those terms.
10
+
11
+ import gdb
12
+
13
+ #===============================================================================
14
+ # GDB Pretty Printing Module for Rust
15
+ #===============================================================================
16
+
17
+ def register_printers (objfile ):
18
+ "Registers Rust pretty printers for the given objfile"
19
+ objfile .pretty_printers .append (rust_pretty_printer_lookup_function )
20
+
21
+ def rust_pretty_printer_lookup_function (val ):
22
+ "Returns the correct Rust pretty printer for the given value if there is one"
23
+ type_code = val .type .code
24
+
25
+ if type_code == gdb .TYPE_CODE_STRUCT :
26
+ struct_kind = classify_struct (val .type )
27
+
28
+ if struct_kind == STRUCT_KIND_STR_SLICE :
29
+ return RustStringSlicePrinter (val )
30
+
31
+ if struct_kind == STRUCT_KIND_TUPLE :
32
+ return RustTuplePrinter (val )
33
+
34
+ if struct_kind == STRUCT_KIND_TUPLE_STRUCT :
35
+ return RustTupleStructPrinter (val , False )
36
+
37
+ if struct_kind == STRUCT_KIND_CSTYLE_VARIANT :
38
+ return RustCStyleEnumPrinter (val [get_field_at_index (val , 0 )])
39
+
40
+ if struct_kind == STRUCT_KIND_TUPLE_VARIANT :
41
+ return RustTupleStructPrinter (val , True )
42
+
43
+ if struct_kind == STRUCT_KIND_STRUCT_VARIANT :
44
+ return RustStructPrinter (val , True )
45
+
46
+ return RustStructPrinter (val , False )
47
+
48
+ # Enum handling
49
+ if type_code == gdb .TYPE_CODE_UNION :
50
+ enum_members = list (val .type .fields ())
51
+ enum_member_count = len (enum_members )
52
+
53
+ if enum_member_count == 0 :
54
+ return RustStructPrinter (val , false )
55
+
56
+ if enum_member_count == 1 :
57
+ if enum_members [0 ].name == None :
58
+ # This is a singleton enum
59
+ return rust_pretty_printer_lookup_function (val [enum_members [0 ]])
60
+ else :
61
+ assert enum_members [0 ].name .startswith ("RUST$ENCODED$ENUM$" )
62
+ # This is a space-optimized enum
63
+ last_separator_index = enum_members [0 ].name .rfind ("$" )
64
+ second_last_separator_index = first_variant_name .rfind ("$" , 0 , last_separator_index )
65
+ disr_field_index = first_variant_name [second_last_separator_index + 1 :
66
+ last_separator_index ]
67
+ disr_field_index = int (disr_field_index )
68
+
69
+ sole_variant_val = val [enum_members [0 ]]
70
+ disr_field = get_field_at_index (sole_variant_val , disr_field_index )
71
+ discriminant = int (sole_variant_val [disr_field ])
72
+
73
+ if discriminant == 0 :
74
+ null_variant_name = first_variant_name [last_separator_index + 1 :]
75
+ return IdentityPrinter (null_variant_name )
76
+
77
+ return rust_pretty_printer_lookup_function (sole_variant_val )
78
+
79
+ # This is a regular enum, extract the discriminant
80
+ discriminant_name , discriminant_val = extract_discriminant_value (val )
81
+ return rust_pretty_printer_lookup_function (val [enum_members [discriminant_val ]])
82
+
83
+
84
+
85
+ return None
86
+
87
+ #=------------------------------------------------------------------------------
88
+ # Pretty Printer Classes
89
+ #=------------------------------------------------------------------------------
90
+
91
+ class RustStructPrinter :
92
+ def __init__ (self , val , hide_first_field ):
93
+ self .val = val
94
+ self .hide_first_field = hide_first_field
95
+
96
+ def to_string (self ):
97
+ return self .val .type .tag
98
+
99
+ def children (self ):
100
+ cs = []
101
+ for field in self .val .type .fields ():
102
+ field_name = field .name ;
103
+ if field_name == None :
104
+ field_name = ""
105
+ name_value_tuple = ( field_name , self .val [field ] )
106
+ cs .append ( name_value_tuple )
107
+
108
+ if self .hide_first_field :
109
+ cs = cs [1 :]
110
+
111
+ return cs
112
+
113
+ class RustTuplePrinter :
114
+ def __init__ (self , val ):
115
+ self .val = val
116
+
117
+ def to_string (self ):
118
+ return None
119
+
120
+ def children (self ):
121
+ cs = []
122
+ for field in self .val .type .fields ():
123
+ cs .append ( ("" , self .val [field ]) )
124
+
125
+ return cs
126
+
127
+ def display_hint (self ):
128
+ return "array"
129
+
130
+ class RustTupleStructPrinter :
131
+ def __init__ (self , val , hide_first_field ):
132
+ self .val = val
133
+ self .hide_first_field = hide_first_field
134
+
135
+ def to_string (self ):
136
+ return self .val .type .tag
137
+
138
+ def children (self ):
139
+ cs = []
140
+ for field in self .val .type .fields ():
141
+ cs .append ( ("" , self .val [field ]) )
142
+
143
+ if self .hide_first_field :
144
+ cs = cs [1 :]
145
+
146
+ return cs
147
+
148
+ def display_hint (self ):
149
+ return "array"
150
+
151
+ class RustStringSlicePrinter :
152
+ def __init__ (self , val ):
153
+ self .val = val
154
+
155
+ def to_string (self ):
156
+ slice_byte_len = self .val ["length" ]
157
+ return '"%s"' % self .val ["data_ptr" ].string (encoding = "utf-8" ,
158
+ length = slice_byte_len )
159
+
160
+ class RustCStyleEnumPrinter :
161
+ def __init__ (self , val ):
162
+ assert val .type .code == gdb .TYPE_CODE_ENUM
163
+ self .val = val
164
+
165
+ def to_string (self ):
166
+ return str (self .val )
167
+
168
+ class IdentityPrinter :
169
+ def __init__ (self , string ):
170
+ self .string
171
+
172
+ def to_string (self ):
173
+ return self .string
174
+
175
+ STRUCT_KIND_REGULAR_STRUCT = 0
176
+ STRUCT_KIND_TUPLE_STRUCT = 1
177
+ STRUCT_KIND_TUPLE = 2
178
+ STRUCT_KIND_TUPLE_VARIANT = 3
179
+ STRUCT_KIND_STRUCT_VARIANT = 4
180
+ STRUCT_KIND_CSTYLE_VARIANT = 5
181
+ STRUCT_KIND_STR_SLICE = 6
182
+
183
+ def classify_struct (type ):
184
+ if type .tag == "&str" :
185
+ return STRUCT_KIND_STR_SLICE
186
+
187
+ fields = list (type .fields ())
188
+ field_count = len (fields )
189
+
190
+ if field_count == 0 :
191
+ return STRUCT_KIND_REGULAR_STRUCT
192
+
193
+ if fields [0 ].artificial :
194
+ if field_count == 1 :
195
+ return STRUCT_KIND_CSTYLE_VARIANT
196
+ elif fields [1 ].name == None :
197
+ return STRUCT_KIND_TUPLE_VARIANT
198
+ else :
199
+ return STRUCT_KIND_STRUCT_VARIANT
200
+
201
+ if fields [0 ].name == None :
202
+ if type .tag .startswith ("(" ):
203
+ return STRUCT_KIND_TUPLE
204
+ else :
205
+ return STRUCT_KIND_TUPLE_STRUCT
206
+
207
+ return STRUCT_KIND_REGULAR_STRUCT
208
+
209
+ def extract_discriminant_value (enum_val ):
210
+ assert enum_val .type .code == gdb .TYPE_CODE_UNION
211
+ for variant_descriptor in enum_val .type .fields ():
212
+ variant_val = enum_val [variant_descriptor ]
213
+ for field in variant_val .type .fields ():
214
+ return (field .name , int (variant_val [field ]))
215
+
216
+ def first_field (val ):
217
+ for field in val .type .fields ():
218
+ return field
219
+
220
+ def get_field_at_index (val , index ):
221
+ i = 0
222
+ for field in val .type .fields ():
223
+ if i == index :
224
+ return field
225
+ return None
0 commit comments