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.
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.
14 import debugger_pretty_printers_common
as rustpp
16 # We want a version of `range` which doesn't allocate an intermediate list,
17 # specifically it should use a lazy iterator. In Python 2 this was `xrange`, but
18 # if we're running with Python 3 then we need to use `range` instead.
19 if sys
.version_info
[0] >= 3:
22 #===============================================================================
23 # GDB Pretty Printing Module for Rust
24 #===============================================================================
26 class GdbType(rustpp
.Type
):
28 def __init__(self
, ty
):
29 super(GdbType
, self
).__init
__()
33 def get_unqualified_type_name(self
):
39 return rustpp
.extract_type_name(tag
).replace("&'static ", "&")
41 def get_dwarf_type_kind(self
):
42 if self
.ty
.code
== gdb
.TYPE_CODE_STRUCT
:
43 return rustpp
.DWARF_TYPE_CODE_STRUCT
45 if self
.ty
.code
== gdb
.TYPE_CODE_UNION
:
46 return rustpp
.DWARF_TYPE_CODE_UNION
48 if self
.ty
.code
== gdb
.TYPE_CODE_PTR
:
49 return rustpp
.DWARF_TYPE_CODE_PTR
51 if self
.ty
.code
== gdb
.TYPE_CODE_ENUM
:
52 return rustpp
.DWARF_TYPE_CODE_ENUM
55 assert ((self
.get_dwarf_type_kind() == rustpp
.DWARF_TYPE_CODE_STRUCT
) or
56 (self
.get_dwarf_type_kind() == rustpp
.DWARF_TYPE_CODE_UNION
))
57 if self
.fields
is None:
58 self
.fields
= list(self
.ty
.fields())
61 def get_wrapped_value(self
):
65 class GdbValue(rustpp
.Value
):
66 def __init__(self
, gdb_val
):
67 super(GdbValue
, self
).__init
__(GdbType(gdb_val
.type))
68 self
.gdb_val
= gdb_val
71 def get_child_at_index(self
, index
):
72 child
= self
.children
.get(index
)
74 gdb_field
= get_field_at_index(self
.gdb_val
, index
)
75 child
= GdbValue(self
.gdb_val
[gdb_field
])
76 self
.children
[index
] = child
80 if self
.gdb_val
.type.code
== gdb
.TYPE_CODE_PTR
:
81 as_str
= rustpp
.compat_str(self
.gdb_val
).split()[0]
83 return int(self
.gdb_val
)
85 def get_wrapped_value(self
):
89 def register_printers(objfile
):
90 """Registers Rust pretty printers for the given objfile"""
91 objfile
.pretty_printers
.append(rust_pretty_printer_lookup_function
)
94 def rust_pretty_printer_lookup_function(gdb_val
):
96 Returns the correct Rust pretty printer for the given value
100 val
= GdbValue(gdb_val
)
101 type_kind
= val
.type.get_type_kind()
103 if type_kind
== rustpp
.TYPE_KIND_EMPTY
:
104 return RustEmptyPrinter(val
)
106 if type_kind
== rustpp
.TYPE_KIND_REGULAR_STRUCT
:
107 return RustStructPrinter(val
,
108 omit_first_field
= False,
109 omit_type_name
= False,
110 is_tuple_like
= False)
112 if type_kind
== rustpp
.TYPE_KIND_STRUCT_VARIANT
:
113 return RustStructPrinter(val
,
114 omit_first_field
= True,
115 omit_type_name
= False,
116 is_tuple_like
= False)
118 if type_kind
== rustpp
.TYPE_KIND_SLICE
:
119 return RustSlicePrinter(val
)
121 if type_kind
== rustpp
.TYPE_KIND_STR_SLICE
:
122 return RustStringSlicePrinter(val
)
124 if type_kind
== rustpp
.TYPE_KIND_STD_VEC
:
125 return RustStdVecPrinter(val
)
127 if type_kind
== rustpp
.TYPE_KIND_STD_STRING
:
128 return RustStdStringPrinter(val
)
130 if type_kind
== rustpp
.TYPE_KIND_OS_STRING
:
131 return RustOsStringPrinter(val
)
133 if type_kind
== rustpp
.TYPE_KIND_TUPLE
:
134 return RustStructPrinter(val
,
135 omit_first_field
= False,
136 omit_type_name
= True,
137 is_tuple_like
= True)
139 if type_kind
== rustpp
.TYPE_KIND_TUPLE_STRUCT
:
140 return RustStructPrinter(val
,
141 omit_first_field
= False,
142 omit_type_name
= False,
143 is_tuple_like
= True)
145 if type_kind
== rustpp
.TYPE_KIND_CSTYLE_VARIANT
:
146 return RustCStyleVariantPrinter(val
.get_child_at_index(0))
148 if type_kind
== rustpp
.TYPE_KIND_TUPLE_VARIANT
:
149 return RustStructPrinter(val
,
150 omit_first_field
= True,
151 omit_type_name
= False,
152 is_tuple_like
= True)
154 if type_kind
== rustpp
.TYPE_KIND_SINGLETON_ENUM
:
155 variant
= get_field_at_index(gdb_val
, 0)
156 return rust_pretty_printer_lookup_function(gdb_val
[variant
])
158 if type_kind
== rustpp
.TYPE_KIND_REGULAR_ENUM
:
159 # This is a regular enum, extract the discriminant
160 discriminant_val
= rustpp
.get_discriminant_value_as_integer(val
)
161 variant
= get_field_at_index(gdb_val
, discriminant_val
)
162 return rust_pretty_printer_lookup_function(gdb_val
[variant
])
164 if type_kind
== rustpp
.TYPE_KIND_COMPRESSED_ENUM
:
165 encoded_enum_info
= rustpp
.EncodedEnumInfo(val
)
166 if encoded_enum_info
.is_null_variant():
167 return IdentityPrinter(encoded_enum_info
.get_null_variant_name())
169 non_null_val
= encoded_enum_info
.get_non_null_variant_val()
170 return rust_pretty_printer_lookup_function(non_null_val
.get_wrapped_value())
172 # No pretty printer has been found
176 #=------------------------------------------------------------------------------
177 # Pretty Printer Classes
178 #=------------------------------------------------------------------------------
179 class RustEmptyPrinter(object):
180 def __init__(self
, val
):
184 return self
.__val
.type.get_unqualified_type_name()
187 class RustStructPrinter(object):
188 def __init__(self
, val
, omit_first_field
, omit_type_name
, is_tuple_like
):
190 self
.__omit
_first
_field
= omit_first_field
191 self
.__omit
_type
_name
= omit_type_name
192 self
.__is
_tuple
_like
= is_tuple_like
195 if self
.__omit
_type
_name
:
197 return self
.__val
.type.get_unqualified_type_name()
201 wrapped_value
= self
.__val
.get_wrapped_value()
203 for number
, field
in enumerate(self
.__val
.type.get_fields()):
204 field_value
= wrapped_value
[field
.name
]
205 if self
.__is
_tuple
_like
:
206 cs
.append((str(number
), field_value
))
208 cs
.append((field
.name
, field_value
))
210 if self
.__omit
_first
_field
:
215 def display_hint(self
):
216 if self
.__is
_tuple
_like
:
222 class RustSlicePrinter(object):
223 def __init__(self
, val
):
231 (length
, data_ptr
) = rustpp
.extract_length_and_ptr_from_slice(self
.__val
)
232 return (self
.__val
.type.get_unqualified_type_name() +
233 ("(len: %i)" % length
))
236 (length
, data_ptr
) = rustpp
.extract_length_and_ptr_from_slice(self
.__val
)
237 assert data_ptr
.type.get_dwarf_type_kind() == rustpp
.DWARF_TYPE_CODE_PTR
238 raw_ptr
= data_ptr
.get_wrapped_value()
240 for index
in xrange(0, length
):
241 yield (str(index
), (raw_ptr
+ index
).dereference())
244 class RustStringSlicePrinter(object):
245 def __init__(self
, val
):
249 (length
, data_ptr
) = rustpp
.extract_length_and_ptr_from_slice(self
.__val
)
250 raw_ptr
= data_ptr
.get_wrapped_value()
251 return '"%s"' % raw_ptr
.string(encoding
="utf-8", length
=length
)
254 class RustStdVecPrinter(object):
255 def __init__(self
, val
):
263 (length
, data_ptr
, cap
) = rustpp
.extract_length_ptr_and_cap_from_std_vec(self
.__val
)
264 return (self
.__val
.type.get_unqualified_type_name() +
265 ("(len: %i, cap: %i)" % (length
, cap
)))
268 (length
, data_ptr
, cap
) = rustpp
.extract_length_ptr_and_cap_from_std_vec(self
.__val
)
269 gdb_ptr
= data_ptr
.get_wrapped_value()
270 for index
in xrange(0, length
):
271 yield (str(index
), (gdb_ptr
+ index
).dereference())
274 class RustStdStringPrinter(object):
275 def __init__(self
, val
):
279 vec
= self
.__val
.get_child_at_index(0)
280 (length
, data_ptr
, cap
) = rustpp
.extract_length_ptr_and_cap_from_std_vec(vec
)
281 return '"%s"' % data_ptr
.get_wrapped_value().string(encoding
="utf-8",
285 class RustOsStringPrinter(object):
286 def __init__(self
, val
):
290 buf
= self
.__val
.get_child_at_index(0)
291 vec
= buf
.get_child_at_index(0)
292 if vec
.type.get_unqualified_type_name() == "Wtf8Buf":
293 vec
= vec
.get_child_at_index(0)
295 (length
, data_ptr
, cap
) = rustpp
.extract_length_ptr_and_cap_from_std_vec(
297 return '"%s"' % data_ptr
.get_wrapped_value().string(length
=length
)
300 class RustCStyleVariantPrinter(object):
301 def __init__(self
, val
):
302 assert val
.type.get_dwarf_type_kind() == rustpp
.DWARF_TYPE_CODE_ENUM
306 return str(self
.__val
.get_wrapped_value())
309 class IdentityPrinter(object):
310 def __init__(self
, string
):
317 def get_field_at_index(gdb_val
, index
):
319 for field
in gdb_val
.type.fields():