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("&[") 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
)