1 # Copyright 2015 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.
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.
12 This module provides an abstraction layer over common Rust pretty printing
13 functionality needed by both GDB and LLDB.
18 # Type codes that indicate the kind of type as it appears in DWARF debug
19 # information. This code alone is not sufficient to determine the Rust type.
20 # For example structs, tuples, fat pointers, or enum variants will all have
21 # DWARF_TYPE_CODE_STRUCT.
22 DWARF_TYPE_CODE_STRUCT = 1
23 DWARF_TYPE_CODE_UNION = 2
24 DWARF_TYPE_CODE_PTR = 3
25 DWARF_TYPE_CODE_ARRAY = 4
26 DWARF_TYPE_CODE_ENUM = 5
28 # These constants specify the most specific kind of type that could be
29 # determined for a given value.
30 TYPE_KIND_UNKNOWN = -1
33 TYPE_KIND_REGULAR_STRUCT = 2
35 TYPE_KIND_TUPLE_STRUCT = 4
36 TYPE_KIND_CSTYLE_VARIANT = 5
37 TYPE_KIND_TUPLE_VARIANT = 6
38 TYPE_KIND_STRUCT_VARIANT = 7
39 TYPE_KIND_STR_SLICE = 8
41 TYPE_KIND_STD_STRING = 10
42 TYPE_KIND_REGULAR_ENUM = 11
43 TYPE_KIND_COMPRESSED_ENUM = 12
44 TYPE_KIND_SINGLETON_ENUM = 13
45 TYPE_KIND_CSTYLE_ENUM = 14
47 TYPE_KIND_FIXED_SIZE_VEC = 16
49 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
50 ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
52 # Slice related constants
53 SLICE_FIELD_NAME_DATA_PTR = "data_ptr"
54 SLICE_FIELD_NAME_LENGTH = "length"
55 SLICE_FIELD_NAMES = [SLICE_FIELD_NAME_DATA_PTR, SLICE_FIELD_NAME_LENGTH]
57 # std::Vec<> related constants
58 STD_VEC_FIELD_NAME_LENGTH = "len"
59 STD_VEC_FIELD_NAME_BUF = "buf"
60 STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
61 STD_VEC_FIELD_NAME_LENGTH]
63 # std::String related constants
64 STD_STRING_FIELD_NAMES = ["vec"]
69 This class provides a common interface for type-oriented operations.
70 Sub-classes are supposed to wrap a debugger-specific type-object and
71 provide implementations for the abstract methods in this class.
75 self.__type_kind = None
77 def get_unqualified_type_name(self):
79 Implementations of this method should return the unqualified name of the
80 type-object they are wrapping. Some examples:
83 'std::vec::Vec<std::string::String>' -> 'Vec<std::string::String>'
84 '&std::option::Option<std::string::String>' -> '&std::option::Option<std::string::String>'
86 As you can see, type arguments stay fully qualified.
88 raise NotImplementedError("Override this method")
90 def get_dwarf_type_kind(self):
92 Implementations of this method should return the correct
93 DWARF_TYPE_CODE_* value for the wrapped type-object.
95 raise NotImplementedError("Override this method")
99 Implementations of this method should return a list of field-objects of
100 this type. For Rust-enums (i.e. with DWARF_TYPE_CODE_UNION) these field-
101 objects represent the variants of the enum. Field-objects must have a
102 `name` attribute that gives their name as specified in DWARF.
104 assert ((self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT) or
105 (self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION))
106 raise NotImplementedError("Override this method")
108 def get_wrapped_value(self):
110 Returns the debugger-specific type-object wrapped by this object. This
111 is sometimes needed for doing things like pointer-arithmetic in GDB.
113 raise NotImplementedError("Override this method")
115 def get_type_kind(self):
116 """This method returns the TYPE_KIND_* value for this type-object."""
117 if self.__type_kind is None:
118 dwarf_type_code = self.get_dwarf_type_kind()
120 if dwarf_type_code == DWARF_TYPE_CODE_STRUCT:
121 self.__type_kind = self.__classify_struct()
122 elif dwarf_type_code == DWARF_TYPE_CODE_UNION:
123 self.__type_kind = self.__classify_union()
124 elif dwarf_type_code == DWARF_TYPE_CODE_PTR:
125 self.__type_kind = TYPE_KIND_PTR
126 elif dwarf_type_code == DWARF_TYPE_CODE_ARRAY:
127 self.__type_kind = TYPE_KIND_FIXED_SIZE_VEC
129 self.__type_kind = TYPE_KIND_UNKNOWN
130 return self.__type_kind
132 def __classify_struct(self):
133 assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT
135 unqualified_type_name = self.get_unqualified_type_name()
138 if unqualified_type_name == "&str":
139 return TYPE_KIND_STR_SLICE
142 if (unqualified_type_name.startswith(("&[", "&mut [")) and
143 unqualified_type_name.endswith("]") and
144 self.__conforms_to_field_layout(SLICE_FIELD_NAMES)):
145 return TYPE_KIND_SLICE
147 fields = self.get_fields()
148 field_count = len(fields)
152 return TYPE_KIND_EMPTY
155 if (unqualified_type_name.startswith("Vec<") and
156 self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
157 return TYPE_KIND_STD_VEC
160 if (unqualified_type_name.startswith("String") and
161 self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
162 return TYPE_KIND_STD_STRING
165 if fields[0].name == ENUM_DISR_FIELD_NAME:
167 return TYPE_KIND_CSTYLE_VARIANT
168 elif self.__all_fields_conform_to_tuple_field_naming(1):
169 return TYPE_KIND_TUPLE_VARIANT
171 return TYPE_KIND_STRUCT_VARIANT
174 if self.__all_fields_conform_to_tuple_field_naming(0):
175 if unqualified_type_name.startswith("("):
176 return TYPE_KIND_TUPLE
178 return TYPE_KIND_TUPLE_STRUCT
181 return TYPE_KIND_REGULAR_STRUCT
184 def __classify_union(self):
185 assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
187 union_members = self.get_fields()
188 union_member_count = len(union_members)
189 if union_member_count == 0:
190 return TYPE_KIND_EMPTY
191 elif union_member_count == 1:
192 first_variant_name = union_members[0].name
193 if first_variant_name is None:
194 return TYPE_KIND_SINGLETON_ENUM
196 assert first_variant_name.startswith(ENCODED_ENUM_PREFIX)
197 return TYPE_KIND_COMPRESSED_ENUM
199 return TYPE_KIND_REGULAR_ENUM
202 def __conforms_to_field_layout(self, expected_fields):
203 actual_fields = self.get_fields()
204 actual_field_count = len(actual_fields)
206 if actual_field_count != len(expected_fields):
209 for i in range(0, actual_field_count):
210 if actual_fields[i].name != expected_fields[i]:
215 def __all_fields_conform_to_tuple_field_naming(self, start_index):
216 fields = self.get_fields()
217 field_count = len(fields)
219 for i in range(start_index, field_count):
220 field_name = fields[i].name
221 if (field_name is None) or (re.match(r"__\d+$", field_name) is None):
228 This class provides a common interface for value-oriented operations.
229 Sub-classes are supposed to wrap a debugger-specific value-object and
230 provide implementations for the abstract methods in this class.
232 def __init__(self, ty):
235 def get_child_at_index(self, index):
236 """Returns the value of the field, array element or variant at the given index"""
237 raise NotImplementedError("Override this method")
239 def as_integer(self):
241 Try to convert the wrapped value into a Python integer. This should
242 always succeed for values that are pointers or actual integers.
244 raise NotImplementedError("Override this method")
246 def get_wrapped_value(self):
248 Returns the debugger-specific value-object wrapped by this object. This
249 is sometimes needed for doing things like pointer-arithmetic in GDB.
251 raise NotImplementedError("Override this method")
254 class EncodedEnumInfo(object):
256 This class provides facilities for handling enum values with compressed
257 encoding where a non-null field in one variant doubles as the discriminant.
260 def __init__(self, enum_val):
261 assert enum_val.type.get_type_kind() == TYPE_KIND_COMPRESSED_ENUM
262 variant_name = enum_val.type.get_fields()[0].name
263 last_separator_index = variant_name.rfind("$")
264 start_index = len(ENCODED_ENUM_PREFIX)
265 indices_substring = variant_name[start_index:last_separator_index].split("$")
266 self.__enum_val = enum_val
267 self.__disr_field_indices = [int(index) for index in indices_substring]
268 self.__null_variant_name = variant_name[last_separator_index + 1:]
270 def is_null_variant(self):
271 ty = self.__enum_val.type
272 sole_variant_val = self.__enum_val.get_child_at_index(0)
273 discriminant_val = sole_variant_val
274 for disr_field_index in self.__disr_field_indices:
275 discriminant_val = discriminant_val.get_child_at_index(disr_field_index)
277 # If the discriminant field is a fat pointer we have to consider the
278 # first word as the true discriminant
279 if discriminant_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT:
280 discriminant_val = discriminant_val.get_child_at_index(0)
282 return discriminant_val.as_integer() == 0
284 def get_non_null_variant_val(self):
285 return self.__enum_val.get_child_at_index(0)
287 def get_null_variant_name(self):
288 return self.__null_variant_name
291 def get_discriminant_value_as_integer(enum_val):
292 assert enum_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
293 # we can take any variant here because the discriminant has to be the same
295 variant_val = enum_val.get_child_at_index(0)
296 disr_val = variant_val.get_child_at_index(0)
297 return disr_val.as_integer()
300 def extract_length_ptr_and_cap_from_std_vec(vec_val):
301 assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
302 length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
303 buf_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_BUF)
305 length = vec_val.get_child_at_index(length_field_index).as_integer()
306 buf = vec_val.get_child_at_index(buf_field_index)
308 vec_ptr_val = buf.get_child_at_index(0)
309 capacity = buf.get_child_at_index(1).as_integer()
310 unique_ptr_val = vec_ptr_val.get_child_at_index(0)
311 data_ptr = unique_ptr_val.get_child_at_index(0)
312 assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
313 return (length, data_ptr, capacity)
315 def extract_length_and_ptr_from_slice(slice_val):
316 assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
317 slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
319 length_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_LENGTH)
320 ptr_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_DATA_PTR)
322 length = slice_val.get_child_at_index(length_field_index).as_integer()
323 data_ptr = slice_val.get_child_at_index(ptr_field_index)
325 assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
326 return (length, data_ptr)