Skip to content

Commit ccee55b

Browse files
committed
---
yaml --- r: 212159 b: refs/heads/tmp c: f90aecf h: refs/heads/master i: 212157: 42ea8be 212155: 3c8fbbd 212151: edca866 212143: f12006c 212127: b13f3db 212095: f1faed5 v: v3
1 parent 6547ae2 commit ccee55b

File tree

16 files changed

+812
-459
lines changed

16 files changed

+812
-459
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ refs/heads/building: 126db549b038c84269a1e4fe46f051b2c15d6970
3232
refs/heads/beta: 62e70d35be3fe532c26a400b499c58a18f18dd3a
3333
refs/heads/windistfix: 7608dbad651f02e837ed05eef3d74a6662a6e928
3434
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
35-
refs/heads/tmp: e1a33aa98758252c806d0bf1966690fe6c96291b
35+
refs/heads/tmp: f90aecff7623c651aeafbd3bee7f04efc32a2738
3636
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3737
refs/tags/homu-tmp: b77d60adb019bb5de05e884a99f3290ec4694137
3838
refs/heads/gate: 97c84447b65164731087ea82685580cc81424412

branches/tmp/configure

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -849,13 +849,6 @@ then
849849
putvar CFG_LOCAL_RUST_ROOT
850850
fi
851851

852-
# Force freebsd to build with clang; gcc doesn't like us there
853-
if [ $CFG_OSTYPE = unknown-freebsd ]
854-
then
855-
step_msg "on FreeBSD, forcing use of clang"
856-
CFG_ENABLE_CLANG=1
857-
fi
858-
859852
# Force bitrig to build with clang; gcc doesn't like us there
860853
if [ $CFG_OSTYPE = unknown-bitrig ]
861854
then

branches/tmp/mk/debuggers.mk

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
## GDB ##
1717
DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB=gdb_load_rust_pretty_printers.py \
18-
gdb_rust_pretty_printing.py
18+
gdb_rust_pretty_printing.py \
19+
debugger_pretty_printers_common.py
1920
DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS=\
2021
$(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB), \
2122
$(CFG_SRC_DIR)src/etc/$(script))
@@ -27,7 +28,8 @@ DEBUGGER_BIN_SCRIPTS_GDB_ABS=\
2728

2829

2930
## LLDB ##
30-
DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py
31+
DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py \
32+
debugger_pretty_printers_common.py
3133
DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS=\
3234
$(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB), \
3335
$(CFG_SRC_DIR)src/etc/$(script))
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
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+
49+
ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
50+
ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
51+
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]
56+
57+
# std::Vec<> related constants
58+
STD_VEC_FIELD_NAME_DATA_PTR = "ptr"
59+
STD_VEC_FIELD_NAME_LENGTH = "len"
60+
STD_VEC_FIELD_NAME_CAPACITY = "cap"
61+
STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_DATA_PTR,
62+
STD_VEC_FIELD_NAME_LENGTH,
63+
STD_VEC_FIELD_NAME_CAPACITY]
64+
65+
# std::String related constants
66+
STD_STRING_FIELD_NAMES = ["vec"]
67+
68+
69+
class Type(object):
70+
"""
71+
This class provides a common interface for type-oriented operations.
72+
Sub-classes are supposed to wrap a debugger-specific type-object and
73+
provide implementations for the abstract methods in this class.
74+
"""
75+
76+
def __init__(self):
77+
self.__type_kind = None
78+
79+
def get_unqualified_type_name(self):
80+
"""
81+
Implementations of this method should return the unqualified name of the
82+
type-object they are wrapping. Some examples:
83+
84+
'int' -> 'int'
85+
'std::vec::Vec<std::string::String>' -> 'Vec<std::string::String>'
86+
'&std::option::Option<std::string::String>' -> '&std::option::Option<std::string::String>'
87+
88+
As you can see, type arguments stay fully qualified.
89+
"""
90+
raise NotImplementedError("Override this method")
91+
92+
def get_dwarf_type_kind(self):
93+
"""
94+
Implementations of this method should return the correct
95+
DWARF_TYPE_CODE_* value for the wrapped type-object.
96+
"""
97+
raise NotImplementedError("Override this method")
98+
99+
def get_fields(self):
100+
"""
101+
Implementations of this method should return a list of field-objects of
102+
this type. For Rust-enums (i.e. with DWARF_TYPE_CODE_UNION) these field-
103+
objects represent the variants of the enum. Field-objects must have a
104+
`name` attribute that gives their name as specified in DWARF.
105+
"""
106+
assert ((self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT) or
107+
(self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION))
108+
raise NotImplementedError("Override this method")
109+
110+
def get_wrapped_value(self):
111+
"""
112+
Returns the debugger-specific type-object wrapped by this object. This
113+
is sometimes needed for doing things like pointer-arithmetic in GDB.
114+
"""
115+
raise NotImplementedError("Override this method")
116+
117+
def get_type_kind(self):
118+
"""This method returns the TYPE_KIND_* value for this type-object."""
119+
if self.__type_kind is None:
120+
dwarf_type_code = self.get_dwarf_type_kind()
121+
122+
if dwarf_type_code == DWARF_TYPE_CODE_STRUCT:
123+
self.__type_kind = self.__classify_struct()
124+
elif dwarf_type_code == DWARF_TYPE_CODE_UNION:
125+
self.__type_kind = self.__classify_union()
126+
elif dwarf_type_code == DWARF_TYPE_CODE_PTR:
127+
self.__type_kind = TYPE_KIND_PTR
128+
elif dwarf_type_code == DWARF_TYPE_CODE_ARRAY:
129+
self.__type_kind = TYPE_KIND_FIXED_SIZE_VEC
130+
else:
131+
self.__type_kind = TYPE_KIND_UNKNOWN
132+
return self.__type_kind
133+
134+
def __classify_struct(self):
135+
assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT
136+
137+
unqualified_type_name = self.get_unqualified_type_name()
138+
139+
# STR SLICE
140+
if unqualified_type_name == "&str":
141+
return TYPE_KIND_STR_SLICE
142+
143+
# REGULAR SLICE
144+
if (unqualified_type_name.startswith("&[") and
145+
unqualified_type_name.endswith("]") and
146+
self.__conforms_to_field_layout(SLICE_FIELD_NAMES)):
147+
return TYPE_KIND_SLICE
148+
149+
fields = self.get_fields()
150+
field_count = len(fields)
151+
152+
# EMPTY STRUCT
153+
if field_count == 0:
154+
return TYPE_KIND_EMPTY
155+
156+
# STD VEC
157+
if (unqualified_type_name.startswith("Vec<") and
158+
self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
159+
return TYPE_KIND_STD_VEC
160+
161+
# STD STRING
162+
if (unqualified_type_name.startswith("String") and
163+
self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
164+
return TYPE_KIND_STD_STRING
165+
166+
# ENUM VARIANTS
167+
if fields[0].name == ENUM_DISR_FIELD_NAME:
168+
if field_count == 1:
169+
return TYPE_KIND_CSTYLE_VARIANT
170+
elif self.__all_fields_conform_to_tuple_field_naming(1):
171+
return TYPE_KIND_TUPLE_VARIANT
172+
else:
173+
return TYPE_KIND_STRUCT_VARIANT
174+
175+
# TUPLE
176+
if self.__all_fields_conform_to_tuple_field_naming(0):
177+
if unqualified_type_name.startswith("("):
178+
return TYPE_KIND_TUPLE
179+
else:
180+
return TYPE_KIND_TUPLE_STRUCT
181+
182+
# REGULAR STRUCT
183+
return TYPE_KIND_REGULAR_STRUCT
184+
185+
186+
def __classify_union(self):
187+
assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
188+
189+
union_members = self.get_fields()
190+
union_member_count = len(union_members)
191+
if union_member_count == 0:
192+
return TYPE_KIND_EMPTY
193+
elif union_member_count == 1:
194+
first_variant_name = union_members[0].name
195+
if first_variant_name is None:
196+
return TYPE_KIND_SINGLETON_ENUM
197+
else:
198+
assert first_variant_name.startswith(ENCODED_ENUM_PREFIX)
199+
return TYPE_KIND_COMPRESSED_ENUM
200+
else:
201+
return TYPE_KIND_REGULAR_ENUM
202+
203+
204+
def __conforms_to_field_layout(self, expected_fields):
205+
actual_fields = self.get_fields()
206+
actual_field_count = len(actual_fields)
207+
208+
if actual_field_count != len(expected_fields):
209+
return False
210+
211+
for i in range(0, actual_field_count):
212+
if actual_fields[i].name != expected_fields[i]:
213+
return False
214+
215+
return True
216+
217+
def __all_fields_conform_to_tuple_field_naming(self, start_index):
218+
fields = self.get_fields()
219+
field_count = len(fields)
220+
221+
for i in range(start_index, field_count):
222+
field_name = fields[i].name
223+
if (field_name is None) or (re.match(r"__\d+$", field_name) is None):
224+
return False
225+
return True
226+
227+
228+
class Value(object):
229+
"""
230+
This class provides a common interface for value-oriented operations.
231+
Sub-classes are supposed to wrap a debugger-specific value-object and
232+
provide implementations for the abstract methods in this class.
233+
"""
234+
def __init__(self, ty):
235+
self.type = ty
236+
237+
def get_child_at_index(self, index):
238+
"""Returns the value of the field, array element or variant at the given index"""
239+
raise NotImplementedError("Override this method")
240+
241+
def as_integer(self):
242+
"""
243+
Try to convert the wrapped value into a Python integer. This should
244+
always succeed for values that are pointers or actual integers.
245+
"""
246+
raise NotImplementedError("Override this method")
247+
248+
def get_wrapped_value(self):
249+
"""
250+
Returns the debugger-specific value-object wrapped by this object. This
251+
is sometimes needed for doing things like pointer-arithmetic in GDB.
252+
"""
253+
raise NotImplementedError("Override this method")
254+
255+
256+
class EncodedEnumInfo(object):
257+
"""
258+
This class provides facilities for handling enum values with compressed
259+
encoding where a non-null field in one variant doubles as the discriminant.
260+
"""
261+
262+
def __init__(self, enum_val):
263+
assert enum_val.type.get_type_kind() == TYPE_KIND_COMPRESSED_ENUM
264+
variant_name = enum_val.type.get_fields()[0].name
265+
last_separator_index = variant_name.rfind("$")
266+
start_index = len(ENCODED_ENUM_PREFIX)
267+
indices_substring = variant_name[start_index:last_separator_index].split("$")
268+
self.__enum_val = enum_val
269+
self.__disr_field_indices = [int(index) for index in indices_substring]
270+
self.__null_variant_name = variant_name[last_separator_index + 1:]
271+
272+
def is_null_variant(self):
273+
ty = self.__enum_val.type
274+
sole_variant_val = self.__enum_val.get_child_at_index(0)
275+
discriminant_val = sole_variant_val
276+
for disr_field_index in self.__disr_field_indices:
277+
discriminant_val = discriminant_val.get_child_at_index(disr_field_index)
278+
279+
# If the discriminant field is a fat pointer we have to consider the
280+
# first word as the true discriminant
281+
if discriminant_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT:
282+
discriminant_val = discriminant_val.get_child_at_index(0)
283+
284+
return discriminant_val.as_integer() == 0
285+
286+
def get_non_null_variant_val(self):
287+
return self.__enum_val.get_child_at_index(0)
288+
289+
def get_null_variant_name(self):
290+
return self.__null_variant_name
291+
292+
293+
def get_discriminant_value_as_integer(enum_val):
294+
assert enum_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
295+
# we can take any variant here because the discriminant has to be the same
296+
# for all of them.
297+
variant_val = enum_val.get_child_at_index(0)
298+
disr_val = variant_val.get_child_at_index(0)
299+
return disr_val.as_integer()
300+
301+
302+
def extract_length_ptr_and_cap_from_std_vec(vec_val):
303+
assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
304+
length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
305+
ptr_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_DATA_PTR)
306+
cap_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_CAPACITY)
307+
308+
length = vec_val.get_child_at_index(length_field_index).as_integer()
309+
vec_ptr_val = vec_val.get_child_at_index(ptr_field_index)
310+
capacity = vec_val.get_child_at_index(cap_field_index).as_integer()
311+
312+
unique_ptr_val = vec_ptr_val.get_child_at_index(0)
313+
data_ptr = unique_ptr_val.get_child_at_index(0)
314+
assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
315+
return (length, data_ptr, capacity)
316+
317+
def extract_length_and_ptr_from_slice(slice_val):
318+
assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
319+
slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
320+
321+
length_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_LENGTH)
322+
ptr_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_DATA_PTR)
323+
324+
length = slice_val.get_child_at_index(length_field_index).as_integer()
325+
data_ptr = slice_val.get_child_at_index(ptr_field_index)
326+
327+
assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
328+
return (length, data_ptr)

0 commit comments

Comments
 (0)