]> git.lizzy.rs Git - rust.git/blob - src/etc/debugger_pretty_printers_common.py
Auto merge of #53190 - sekineh:thumb-cortex-m, r=jamesmunns
[rust.git] / src / etc / debugger_pretty_printers_common.py
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.
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 """
12 This module provides an abstraction layer over common Rust pretty printing
13 functionality needed by both GDB and LLDB.
14 """
15
16 import re
17
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
27
28 # These constants specify the most specific kind of type that could be
29 # determined for a given value.
30 TYPE_KIND_UNKNOWN           = -1
31 TYPE_KIND_EMPTY             = 0
32 TYPE_KIND_SLICE             = 1
33 TYPE_KIND_REGULAR_STRUCT    = 2
34 TYPE_KIND_TUPLE             = 3
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
40 TYPE_KIND_STD_VEC           = 9
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
46 TYPE_KIND_PTR               = 15
47 TYPE_KIND_FIXED_SIZE_VEC    = 16
48 TYPE_KIND_REGULAR_UNION     = 17
49 TYPE_KIND_OS_STRING         = 18
50 TYPE_KIND_STD_VECDEQUE      = 19
51 TYPE_KIND_STD_BTREESET      = 20
52
53 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
54 ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
55
56 # Slice related constants
57 SLICE_FIELD_NAME_DATA_PTR = "data_ptr"
58 SLICE_FIELD_NAME_LENGTH = "length"
59 SLICE_FIELD_NAMES = [SLICE_FIELD_NAME_DATA_PTR, SLICE_FIELD_NAME_LENGTH]
60
61 # std::Vec<> related constants
62 STD_VEC_FIELD_NAME_LENGTH = "len"
63 STD_VEC_FIELD_NAME_BUF = "buf"
64 STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
65                        STD_VEC_FIELD_NAME_LENGTH]
66
67 # std::collections::VecDeque<> related constants
68 STD_VECDEQUE_FIELD_NAME_TAIL = "tail"
69 STD_VECDEQUE_FIELD_NAME_HEAD = "head"
70 STD_VECDEQUE_FIELD_NAME_BUF = "buf"
71 STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL,
72                             STD_VECDEQUE_FIELD_NAME_HEAD,
73                             STD_VECDEQUE_FIELD_NAME_BUF]
74
75 # std::collections::BTreeSet<> related constants
76 STD_BTREESET_FIELD_NAMES = ["map"]
77
78 # std::String related constants
79 STD_STRING_FIELD_NAMES = ["vec"]
80
81 # std::ffi::OsString related constants
82 OS_STRING_FIELD_NAMES = ["inner"]
83
84
85 class Type(object):
86     """
87     This class provides a common interface for type-oriented operations.
88     Sub-classes are supposed to wrap a debugger-specific type-object and
89     provide implementations for the abstract methods in this class.
90     """
91
92     def __init__(self):
93         self.__type_kind = None
94
95     def get_unqualified_type_name(self):
96         """
97         Implementations of this method should return the unqualified name of the
98         type-object they are wrapping. Some examples:
99
100         'int' -> 'int'
101         'std::vec::Vec<std::string::String>' -> 'Vec<std::string::String>'
102         '&std::option::Option<std::string::String>' -> '&std::option::Option<std::string::String>'
103
104         As you can see, type arguments stay fully qualified.
105         """
106         raise NotImplementedError("Override this method")
107
108     def get_dwarf_type_kind(self):
109         """
110         Implementations of this method should return the correct
111         DWARF_TYPE_CODE_* value for the wrapped type-object.
112         """
113         raise NotImplementedError("Override this method")
114
115     def get_fields(self):
116         """
117         Implementations of this method should return a list of field-objects of
118         this type. For Rust-enums (i.e. with DWARF_TYPE_CODE_UNION) these field-
119         objects represent the variants of the enum. Field-objects must have a
120         `name` attribute that gives their name as specified in DWARF.
121         """
122         assert ((self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT) or
123                 (self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION))
124         raise NotImplementedError("Override this method")
125
126     def get_wrapped_value(self):
127         """
128         Returns the debugger-specific type-object wrapped by this object. This
129         is sometimes needed for doing things like pointer-arithmetic in GDB.
130         """
131         raise NotImplementedError("Override this method")
132
133     def get_type_kind(self):
134         """This method returns the TYPE_KIND_* value for this type-object."""
135         if self.__type_kind is None:
136             dwarf_type_code = self.get_dwarf_type_kind()
137
138             if dwarf_type_code == DWARF_TYPE_CODE_STRUCT:
139                 self.__type_kind = self.__classify_struct()
140             elif dwarf_type_code == DWARF_TYPE_CODE_UNION:
141                 self.__type_kind = self.__classify_union()
142             elif dwarf_type_code == DWARF_TYPE_CODE_PTR:
143                 self.__type_kind = TYPE_KIND_PTR
144             elif dwarf_type_code == DWARF_TYPE_CODE_ARRAY:
145                 self.__type_kind = TYPE_KIND_FIXED_SIZE_VEC
146             else:
147                 self.__type_kind = TYPE_KIND_UNKNOWN
148         return self.__type_kind
149
150     def __classify_struct(self):
151         assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT
152
153         unqualified_type_name = self.get_unqualified_type_name()
154
155         # STR SLICE
156         if unqualified_type_name == "&str":
157             return TYPE_KIND_STR_SLICE
158
159         # REGULAR SLICE
160         if (unqualified_type_name.startswith(("&[", "&mut [")) and
161             unqualified_type_name.endswith("]") and
162             self.__conforms_to_field_layout(SLICE_FIELD_NAMES)):
163             return TYPE_KIND_SLICE
164
165         fields = self.get_fields()
166         field_count = len(fields)
167
168         # EMPTY STRUCT
169         if field_count == 0:
170             return TYPE_KIND_EMPTY
171
172         # STD VEC
173         if (unqualified_type_name.startswith("Vec<") and
174             self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
175             return TYPE_KIND_STD_VEC
176
177         # STD COLLECTION VECDEQUE
178         if (unqualified_type_name.startswith("VecDeque<") and
179             self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)):
180             return TYPE_KIND_STD_VECDEQUE
181
182         # STD COLLECTION BTREESET
183         if (unqualified_type_name.startswith("BTreeSet<") and
184                 self.__conforms_to_field_layout(STD_BTREESET_FIELD_NAMES)):
185             return TYPE_KIND_STD_BTREESET
186
187         # STD STRING
188         if (unqualified_type_name.startswith("String") and
189             self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
190             return TYPE_KIND_STD_STRING
191
192         # OS STRING
193         if (unqualified_type_name == "OsString" and
194             self.__conforms_to_field_layout(OS_STRING_FIELD_NAMES)):
195             return TYPE_KIND_OS_STRING
196
197         # ENUM VARIANTS
198         if fields[0].name == ENUM_DISR_FIELD_NAME:
199             if field_count == 1:
200                 return TYPE_KIND_CSTYLE_VARIANT
201             elif self.__all_fields_conform_to_tuple_field_naming(1):
202                 return TYPE_KIND_TUPLE_VARIANT
203             else:
204                 return TYPE_KIND_STRUCT_VARIANT
205
206         # TUPLE
207         if self.__all_fields_conform_to_tuple_field_naming(0):
208             if unqualified_type_name.startswith("("):
209                 return TYPE_KIND_TUPLE
210             else:
211                 return TYPE_KIND_TUPLE_STRUCT
212
213         # REGULAR STRUCT
214         return TYPE_KIND_REGULAR_STRUCT
215
216
217     def __classify_union(self):
218         assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
219
220         union_members = self.get_fields()
221         union_member_count = len(union_members)
222         if union_member_count == 0:
223             return TYPE_KIND_EMPTY
224
225         first_variant_name = union_members[0].name
226         if first_variant_name is None:
227             if union_member_count == 1:
228                 return TYPE_KIND_SINGLETON_ENUM
229             else:
230                 return TYPE_KIND_REGULAR_ENUM
231         elif first_variant_name.startswith(ENCODED_ENUM_PREFIX):
232             assert union_member_count == 1
233             return TYPE_KIND_COMPRESSED_ENUM
234         else:
235             return TYPE_KIND_REGULAR_UNION
236
237
238     def __conforms_to_field_layout(self, expected_fields):
239         actual_fields = self.get_fields()
240         actual_field_count = len(actual_fields)
241
242         if actual_field_count != len(expected_fields):
243             return False
244
245         for i in range(0, actual_field_count):
246             if actual_fields[i].name != expected_fields[i]:
247                 return False
248
249         return True
250
251     def __all_fields_conform_to_tuple_field_naming(self, start_index):
252         fields = self.get_fields()
253         field_count = len(fields)
254
255         for i in range(start_index, field_count):
256             field_name = fields[i].name
257             if (field_name is None) or (re.match(r"__\d+$", field_name) is None):
258                 return False
259         return True
260
261
262 class Value(object):
263     """
264     This class provides a common interface for value-oriented operations.
265     Sub-classes are supposed to wrap a debugger-specific value-object and
266     provide implementations for the abstract methods in this class.
267     """
268     def __init__(self, ty):
269         self.type = ty
270
271     def get_child_at_index(self, index):
272         """Returns the value of the field, array element or variant at the given index"""
273         raise NotImplementedError("Override this method")
274
275     def as_integer(self):
276         """
277         Try to convert the wrapped value into a Python integer. This should
278         always succeed for values that are pointers or actual integers.
279         """
280         raise NotImplementedError("Override this method")
281
282     def get_wrapped_value(self):
283         """
284         Returns the debugger-specific value-object wrapped by this object. This
285         is sometimes needed for doing things like pointer-arithmetic in GDB.
286         """
287         raise NotImplementedError("Override this method")
288
289
290 class EncodedEnumInfo(object):
291     """
292     This class provides facilities for handling enum values with compressed
293     encoding where a non-null field in one variant doubles as the discriminant.
294     """
295
296     def __init__(self, enum_val):
297         assert enum_val.type.get_type_kind() == TYPE_KIND_COMPRESSED_ENUM
298         variant_name = enum_val.type.get_fields()[0].name
299         last_separator_index = variant_name.rfind("$")
300         start_index = len(ENCODED_ENUM_PREFIX)
301         indices_substring = variant_name[start_index:last_separator_index].split("$")
302         self.__enum_val = enum_val
303         self.__disr_field_indices = [int(index) for index in indices_substring]
304         self.__null_variant_name = variant_name[last_separator_index + 1:]
305
306     def is_null_variant(self):
307         ty = self.__enum_val.type
308         sole_variant_val = self.__enum_val.get_child_at_index(0)
309         discriminant_val = sole_variant_val
310         for disr_field_index in self.__disr_field_indices:
311             discriminant_val = discriminant_val.get_child_at_index(disr_field_index)
312
313         # If the discriminant field is a fat pointer we have to consider the
314         # first word as the true discriminant
315         if discriminant_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT:
316             discriminant_val = discriminant_val.get_child_at_index(0)
317
318         return discriminant_val.as_integer() == 0
319
320     def get_non_null_variant_val(self):
321         return self.__enum_val.get_child_at_index(0)
322
323     def get_null_variant_name(self):
324         return self.__null_variant_name
325
326
327 def get_discriminant_value_as_integer(enum_val):
328     assert enum_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
329     # we can take any variant here because the discriminant has to be the same
330     # for all of them.
331     variant_val = enum_val.get_child_at_index(0)
332     disr_val = variant_val.get_child_at_index(0)
333     return disr_val.as_integer()
334
335
336 def extract_length_ptr_and_cap_from_std_vec(vec_val):
337     assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
338     length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
339     buf_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_BUF)
340
341     length = vec_val.get_child_at_index(length_field_index).as_integer()
342     buf = vec_val.get_child_at_index(buf_field_index)
343
344     vec_ptr_val = buf.get_child_at_index(0)
345     capacity = buf.get_child_at_index(1).as_integer()
346     unique_ptr_val = vec_ptr_val.get_child_at_index(0)
347     data_ptr = unique_ptr_val.get_child_at_index(0)
348     assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
349     return (length, data_ptr, capacity)
350
351
352 def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val):
353     assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE
354     tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL)
355     head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD)
356     buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF)
357
358     tail = vec_val.get_child_at_index(tail_field_index).as_integer()
359     head = vec_val.get_child_at_index(head_field_index).as_integer()
360     buf = vec_val.get_child_at_index(buf_field_index)
361
362     vec_ptr_val = buf.get_child_at_index(0)
363     capacity = buf.get_child_at_index(1).as_integer()
364     unique_ptr_val = vec_ptr_val.get_child_at_index(0)
365     data_ptr = unique_ptr_val.get_child_at_index(0)
366     assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
367     return (tail, head, data_ptr, capacity)
368
369
370 def extract_length_and_ptr_from_std_btreeset(vec_val):
371     assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREESET
372     map = vec_val.get_child_at_index(0)
373     root = map.get_child_at_index(0)
374     length = map.get_child_at_index(1).as_integer()
375     node = root.get_child_at_index(0)
376     ptr = node.get_child_at_index(0)
377     unique_ptr_val = ptr.get_child_at_index(0)
378     data_ptr = unique_ptr_val.get_child_at_index(0)
379     assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
380     return (length, data_ptr)
381
382
383 def extract_length_and_ptr_from_slice(slice_val):
384     assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
385             slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
386
387     length_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_LENGTH)
388     ptr_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_DATA_PTR)
389
390     length = slice_val.get_child_at_index(length_field_index).as_integer()
391     data_ptr = slice_val.get_child_at_index(ptr_field_index)
392
393     assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
394     return (length, data_ptr)
395
396 UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"])
397
398 def extract_type_name(qualified_type_name):
399     """Extracts the type name from a fully qualified path"""
400     if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS:
401         return qualified_type_name
402
403     end_of_search = qualified_type_name.find("<")
404     if end_of_search < 0:
405         end_of_search = len(qualified_type_name)
406
407     index = qualified_type_name.rfind("::", 0, end_of_search)
408     if index < 0:
409         return qualified_type_name
410     else:
411         return qualified_type_name[index + 2:]
412
413 try:
414     compat_str = unicode  # Python 2
415 except NameError:
416     compat_str = str