]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | |
9346a6ac | 12 | import re |
62682a34 | 13 | import debugger_pretty_printers_common as rustpp |
1a4d82fc JJ |
14 | |
15 | #=============================================================================== | |
16 | # GDB Pretty Printing Module for Rust | |
17 | #=============================================================================== | |
18 | ||
62682a34 | 19 | class GdbType(rustpp.Type): |
85aaf69f | 20 | |
62682a34 SL |
21 | def __init__(self, ty): |
22 | super(GdbType, self).__init__() | |
23 | self.ty = ty | |
24 | self.fields = None | |
85aaf69f | 25 | |
62682a34 SL |
26 | def get_unqualified_type_name(self): |
27 | tag = self.ty.tag | |
1a4d82fc | 28 | |
62682a34 SL |
29 | if tag is None: |
30 | return tag | |
85aaf69f | 31 | |
62682a34 | 32 | return tag.replace("&'static ", "&") |
85aaf69f | 33 | |
62682a34 SL |
34 | def get_dwarf_type_kind(self): |
35 | if self.ty.code == gdb.TYPE_CODE_STRUCT: | |
36 | return rustpp.DWARF_TYPE_CODE_STRUCT | |
c34b1796 | 37 | |
62682a34 SL |
38 | if self.ty.code == gdb.TYPE_CODE_UNION: |
39 | return rustpp.DWARF_TYPE_CODE_UNION | |
85aaf69f | 40 | |
62682a34 SL |
41 | if self.ty.code == gdb.TYPE_CODE_PTR: |
42 | return rustpp.DWARF_TYPE_CODE_PTR | |
c34b1796 | 43 | |
62682a34 SL |
44 | if self.ty.code == gdb.TYPE_CODE_ENUM: |
45 | return rustpp.DWARF_TYPE_CODE_ENUM | |
c34b1796 | 46 | |
62682a34 SL |
47 | def get_fields(self): |
48 | assert ((self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT) or | |
49 | (self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION)) | |
50 | if self.fields is None: | |
51 | self.fields = list(self.ty.fields()) | |
52 | return self.fields | |
85aaf69f | 53 | |
62682a34 SL |
54 | def get_wrapped_value(self): |
55 | return self.ty | |
85aaf69f | 56 | |
85aaf69f | 57 | |
62682a34 SL |
58 | class GdbValue(rustpp.Value): |
59 | def __init__(self, gdb_val): | |
60 | super(GdbValue, self).__init__(GdbType(gdb_val.type)) | |
61 | self.gdb_val = gdb_val | |
62 | self.children = {} | |
85aaf69f | 63 | |
62682a34 SL |
64 | def get_child_at_index(self, index): |
65 | child = self.children.get(index) | |
66 | if child is None: | |
67 | gdb_field = get_field_at_index(self.gdb_val, index) | |
68 | child = GdbValue(self.gdb_val[gdb_field]) | |
69 | self.children[index] = child | |
70 | return child | |
85aaf69f | 71 | |
62682a34 SL |
72 | def as_integer(self): |
73 | return int(self.gdb_val) | |
85aaf69f | 74 | |
62682a34 SL |
75 | def get_wrapped_value(self): |
76 | return self.gdb_val | |
85aaf69f | 77 | |
85aaf69f | 78 | |
62682a34 SL |
79 | def register_printers(objfile): |
80 | """Registers Rust pretty printers for the given objfile""" | |
81 | objfile.pretty_printers.append(rust_pretty_printer_lookup_function) | |
85aaf69f | 82 | |
85aaf69f | 83 | |
62682a34 SL |
84 | def rust_pretty_printer_lookup_function(gdb_val): |
85 | """ | |
86 | Returns the correct Rust pretty printer for the given value | |
87 | if there is one | |
88 | """ | |
1a4d82fc | 89 | |
62682a34 SL |
90 | val = GdbValue(gdb_val) |
91 | type_kind = val.type.get_type_kind() | |
1a4d82fc | 92 | |
62682a34 SL |
93 | if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or |
94 | type_kind == rustpp.TYPE_KIND_EMPTY): | |
95 | return RustStructPrinter(val, | |
96 | omit_first_field = False, | |
97 | omit_type_name = False, | |
98 | is_tuple_like = False) | |
85aaf69f | 99 | |
62682a34 SL |
100 | if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: |
101 | return RustStructPrinter(val, | |
102 | omit_first_field = True, | |
103 | omit_type_name = False, | |
104 | is_tuple_like = False) | |
85aaf69f | 105 | |
62682a34 SL |
106 | if type_kind == rustpp.TYPE_KIND_SLICE: |
107 | return RustSlicePrinter(val) | |
85aaf69f | 108 | |
62682a34 SL |
109 | if type_kind == rustpp.TYPE_KIND_STR_SLICE: |
110 | return RustStringSlicePrinter(val) | |
85aaf69f | 111 | |
62682a34 SL |
112 | if type_kind == rustpp.TYPE_KIND_STD_VEC: |
113 | return RustStdVecPrinter(val) | |
85aaf69f | 114 | |
62682a34 SL |
115 | if type_kind == rustpp.TYPE_KIND_STD_STRING: |
116 | return RustStdStringPrinter(val) | |
1a4d82fc | 117 | |
62682a34 SL |
118 | if type_kind == rustpp.TYPE_KIND_TUPLE: |
119 | return RustStructPrinter(val, | |
120 | omit_first_field = False, | |
121 | omit_type_name = True, | |
122 | is_tuple_like = True) | |
1a4d82fc | 123 | |
62682a34 SL |
124 | if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT: |
125 | return RustStructPrinter(val, | |
126 | omit_first_field = False, | |
127 | omit_type_name = False, | |
128 | is_tuple_like = True) | |
85aaf69f | 129 | |
62682a34 SL |
130 | if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT: |
131 | return RustCStyleVariantPrinter(val.get_child_at_index(0)) | |
1a4d82fc | 132 | |
62682a34 SL |
133 | if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT: |
134 | return RustStructPrinter(val, | |
135 | omit_first_field = True, | |
136 | omit_type_name = False, | |
137 | is_tuple_like = True) | |
1a4d82fc | 138 | |
62682a34 SL |
139 | if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM: |
140 | variant = get_field_at_index(gdb_val, 0) | |
141 | return rust_pretty_printer_lookup_function(gdb_val[variant]) | |
1a4d82fc | 142 | |
62682a34 SL |
143 | if type_kind == rustpp.TYPE_KIND_REGULAR_ENUM: |
144 | # This is a regular enum, extract the discriminant | |
145 | discriminant_val = rustpp.get_discriminant_value_as_integer(val) | |
146 | variant = get_field_at_index(gdb_val, discriminant_val) | |
147 | return rust_pretty_printer_lookup_function(gdb_val[variant]) | |
148 | ||
149 | if type_kind == rustpp.TYPE_KIND_COMPRESSED_ENUM: | |
150 | encoded_enum_info = rustpp.EncodedEnumInfo(val) | |
151 | if encoded_enum_info.is_null_variant(): | |
152 | return IdentityPrinter(encoded_enum_info.get_null_variant_name()) | |
1a4d82fc | 153 | |
62682a34 SL |
154 | non_null_val = encoded_enum_info.get_non_null_variant_val() |
155 | return rust_pretty_printer_lookup_function(non_null_val.get_wrapped_value()) | |
156 | ||
157 | # No pretty printer has been found | |
158 | return None | |
159 | ||
160 | ||
161 | #=------------------------------------------------------------------------------ | |
162 | # Pretty Printer Classes | |
163 | #=------------------------------------------------------------------------------ | |
164 | class RustStructPrinter: | |
165 | def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like): | |
166 | self.__val = val | |
167 | self.__omit_first_field = omit_first_field | |
168 | self.__omit_type_name = omit_type_name | |
169 | self.__is_tuple_like = is_tuple_like | |
1a4d82fc | 170 | |
85aaf69f | 171 | def to_string(self): |
62682a34 SL |
172 | if self.__omit_type_name: |
173 | return None | |
174 | return self.__val.type.get_unqualified_type_name() | |
1a4d82fc | 175 | |
85aaf69f SL |
176 | def children(self): |
177 | cs = [] | |
62682a34 SL |
178 | wrapped_value = self.__val.get_wrapped_value() |
179 | ||
180 | for field in self.__val.type.get_fields(): | |
181 | field_value = wrapped_value[field.name] | |
182 | if self.__is_tuple_like: | |
183 | cs.append(("", field_value)) | |
184 | else: | |
185 | cs.append((field.name, field_value)) | |
1a4d82fc | 186 | |
62682a34 | 187 | if self.__omit_first_field: |
85aaf69f | 188 | cs = cs[1:] |
1a4d82fc | 189 | |
85aaf69f SL |
190 | return cs |
191 | ||
192 | def display_hint(self): | |
62682a34 SL |
193 | if self.__is_tuple_like: |
194 | return "array" | |
195 | else: | |
196 | return "" | |
197 | ||
1a4d82fc | 198 | |
c34b1796 AL |
199 | class RustSlicePrinter: |
200 | def __init__(self, val): | |
62682a34 | 201 | self.__val = val |
c34b1796 AL |
202 | |
203 | def display_hint(self): | |
204 | return "array" | |
205 | ||
206 | def to_string(self): | |
62682a34 SL |
207 | (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val) |
208 | return (self.__val.type.get_unqualified_type_name() + | |
209 | ("(len: %i)" % length)) | |
c34b1796 AL |
210 | |
211 | def children(self): | |
212 | cs = [] | |
62682a34 SL |
213 | (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val) |
214 | assert data_ptr.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR | |
215 | raw_ptr = data_ptr.get_wrapped_value() | |
c34b1796 AL |
216 | |
217 | for index in range(0, length): | |
62682a34 | 218 | cs.append((str(index), (raw_ptr + index).dereference())) |
c34b1796 AL |
219 | |
220 | return cs | |
1a4d82fc | 221 | |
62682a34 | 222 | |
1a4d82fc | 223 | class RustStringSlicePrinter: |
85aaf69f | 224 | def __init__(self, val): |
62682a34 | 225 | self.__val = val |
85aaf69f SL |
226 | |
227 | def to_string(self): | |
62682a34 SL |
228 | (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val) |
229 | raw_ptr = data_ptr.get_wrapped_value() | |
230 | return '"%s"' % raw_ptr.string(encoding="utf-8", length=length) | |
231 | ||
1a4d82fc | 232 | |
c34b1796 AL |
233 | class RustStdVecPrinter: |
234 | def __init__(self, val): | |
62682a34 | 235 | self.__val = val |
c34b1796 AL |
236 | |
237 | def display_hint(self): | |
238 | return "array" | |
239 | ||
240 | def to_string(self): | |
62682a34 SL |
241 | (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val) |
242 | return (self.__val.type.get_unqualified_type_name() + | |
243 | ("(len: %i, cap: %i)" % (length, cap))) | |
c34b1796 AL |
244 | |
245 | def children(self): | |
246 | cs = [] | |
62682a34 SL |
247 | (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val) |
248 | gdb_ptr = data_ptr.get_wrapped_value() | |
c34b1796 | 249 | for index in range(0, length): |
62682a34 | 250 | cs.append((str(index), (gdb_ptr + index).dereference())) |
c34b1796 AL |
251 | return cs |
252 | ||
62682a34 | 253 | |
c34b1796 AL |
254 | class RustStdStringPrinter: |
255 | def __init__(self, val): | |
62682a34 | 256 | self.__val = val |
c34b1796 AL |
257 | |
258 | def to_string(self): | |
62682a34 SL |
259 | vec = self.__val.get_child_at_index(0) |
260 | (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec) | |
261 | return '"%s"' % data_ptr.get_wrapped_value().string(encoding="utf-8", | |
262 | length=length) | |
c34b1796 | 263 | |
1a4d82fc | 264 | |
62682a34 | 265 | class RustCStyleVariantPrinter: |
85aaf69f | 266 | def __init__(self, val): |
62682a34 SL |
267 | assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM |
268 | self.__val = val | |
85aaf69f SL |
269 | |
270 | def to_string(self): | |
62682a34 | 271 | return str(self.__val.get_wrapped_value()) |
1a4d82fc | 272 | |
1a4d82fc JJ |
273 | |
274 | class IdentityPrinter: | |
85aaf69f SL |
275 | def __init__(self, string): |
276 | self.string = string | |
1a4d82fc | 277 | |
85aaf69f SL |
278 | def to_string(self): |
279 | return self.string | |
1a4d82fc | 280 | |
1a4d82fc | 281 | |
62682a34 | 282 | def get_field_at_index(gdb_val, index): |
85aaf69f | 283 | i = 0 |
62682a34 | 284 | for field in gdb_val.type.fields(): |
85aaf69f SL |
285 | if i == index: |
286 | return field | |
287 | i += 1 | |
288 | return None |