]> git.proxmox.com Git - rustc.git/blame - src/etc/gdb_providers.py
New upstream version 1.47.0+dfsg1
[rustc.git] / src / etc / gdb_providers.py
CommitLineData
f035d41b
XL
1from sys import version_info
2
3import gdb
4from gdb import lookup_type
5
6if version_info[0] >= 3:
7 xrange = range
8
9ZERO_FIELD = "__0"
10FIRST_FIELD = "__1"
11
12
13def unwrap_unique_or_non_null(unique_or_nonnull):
14 # BACKCOMPAT: rust 1.32
15 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
16 ptr = unique_or_nonnull["pointer"]
17 return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD]
18
19
20class EnumProvider:
21 def __init__(self, valobj):
22 content = valobj[valobj.type.fields()[0]]
23 fields = content.type.fields()
24 self.empty = len(fields) == 0
25 if not self.empty:
26 if len(fields) == 1:
27 discriminant = 0
28 else:
29 discriminant = int(content[fields[0]]) + 1
30 self.active_variant = content[fields[discriminant]]
31 self.name = fields[discriminant].name
32 self.full_name = "{}::{}".format(valobj.type.name, self.name)
33 else:
34 self.full_name = valobj.type.name
35
36 def to_string(self):
37 return self.full_name
38
39 def children(self):
40 if not self.empty:
41 yield self.name, self.active_variant
42
43
44class StdStringProvider:
45 def __init__(self, valobj):
46 self.valobj = valobj
47 vec = valobj["vec"]
48 self.length = int(vec["len"])
49 self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
50
51 def to_string(self):
52 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
53
54 @staticmethod
55 def display_hint():
56 return "string"
57
58
59class StdOsStringProvider:
60 def __init__(self, valobj):
61 self.valobj = valobj
62 buf = self.valobj["inner"]["inner"]
63 is_windows = "Wtf8Buf" in buf.type.name
64 vec = buf[ZERO_FIELD] if is_windows else buf
65
66 self.length = int(vec["len"])
67 self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
68
69 def to_string(self):
70 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
71
72 def display_hint(self):
73 return "string"
74
75
76class StdStrProvider:
77 def __init__(self, valobj):
78 self.valobj = valobj
79 self.length = int(valobj["length"])
80 self.data_ptr = valobj["data_ptr"]
81
82 def to_string(self):
83 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
84
85 @staticmethod
86 def display_hint():
87 return "string"
88
89
90class StdVecProvider:
91 def __init__(self, valobj):
92 self.valobj = valobj
93 self.length = int(valobj["len"])
94 self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
95
96 def to_string(self):
97 return "Vec(size={})".format(self.length)
98
99 def children(self):
100 saw_inaccessible = False
101 for index in xrange(self.length):
102 element_ptr = self.data_ptr + index
103 if saw_inaccessible:
104 return
105 try:
106 # rust-lang/rust#64343: passing deref expr to `str` allows
107 # catching exception on garbage pointer
108 str(element_ptr.dereference())
109 yield "[{}]".format(index), element_ptr.dereference()
110 except RuntimeError:
111 saw_inaccessible = True
112 yield str(index), "inaccessible"
113
114 @staticmethod
115 def display_hint():
116 return "array"
117
118
119class StdVecDequeProvider:
120 def __init__(self, valobj):
121 self.valobj = valobj
122 self.head = int(valobj["head"])
123 self.tail = int(valobj["tail"])
124 self.cap = int(valobj["buf"]["cap"])
125 self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
126 if self.head >= self.tail:
127 self.size = self.head - self.tail
128 else:
129 self.size = self.cap + self.head - self.tail
130
131 def to_string(self):
132 return "VecDeque(size={})".format(self.size)
133
134 def children(self):
135 for index in xrange(0, self.size):
136 value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference()
137 yield "[{}]".format(index), value
138
139 @staticmethod
140 def display_hint():
141 return "array"
142
143
144class StdRcProvider:
145 def __init__(self, valobj, is_atomic=False):
146 self.valobj = valobj
147 self.is_atomic = is_atomic
148 self.ptr = unwrap_unique_or_non_null(valobj["ptr"])
149 self.value = self.ptr["data" if is_atomic else "value"]
150 self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"]
151 self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"] - 1
152
153 def to_string(self):
154 if self.is_atomic:
155 return "Arc(strong={}, weak={})".format(int(self.strong), int(self.weak))
156 else:
157 return "Rc(strong={}, weak={})".format(int(self.strong), int(self.weak))
158
159 def children(self):
160 yield "value", self.value
161 yield "strong", self.strong
162 yield "weak", self.weak
163
164
165class StdCellProvider:
166 def __init__(self, valobj):
167 self.value = valobj["value"]["value"]
168
169 def to_string(self):
170 return "Cell"
171
172 def children(self):
173 yield "value", self.value
174
175
176class StdRefProvider:
177 def __init__(self, valobj):
178 self.value = valobj["value"].dereference()
179 self.borrow = valobj["borrow"]["borrow"]["value"]["value"]
180
181 def to_string(self):
182 borrow = int(self.borrow)
183 if borrow >= 0:
184 return "Ref(borrow={})".format(borrow)
185 else:
186 return "Ref(borrow_mut={})".format(-borrow)
187
188 def children(self):
189 yield "*value", self.value
190 yield "borrow", self.borrow
191
192
193class StdRefCellProvider:
194 def __init__(self, valobj):
195 self.value = valobj["value"]["value"]
196 self.borrow = valobj["borrow"]["value"]["value"]
197
198 def to_string(self):
199 borrow = int(self.borrow)
200 if borrow >= 0:
201 return "RefCell(borrow={})".format(borrow)
202 else:
203 return "RefCell(borrow_mut={})".format(-borrow)
204
205 def children(self):
206 yield "value", self.value
207 yield "borrow", self.borrow
208
209
210# Yield each key (and optionally value) from a BoxedNode.
211def children_of_node(boxed_node, height, want_values):
212 def cast_to_internal(node):
213 internal_type_name = str(node.type.target()).replace("LeafNode", "InternalNode", 1)
214 internal_type = lookup_type(internal_type_name)
215 return node.cast(internal_type.pointer())
216
217 node_ptr = unwrap_unique_or_non_null(boxed_node["ptr"])
218 node_ptr = cast_to_internal(node_ptr) if height > 0 else node_ptr
219 leaf = node_ptr["data"] if height > 0 else node_ptr.dereference()
220 keys = leaf["keys"]
221 values = leaf["vals"]
222 length = int(leaf["len"])
223
224 for i in xrange(0, length + 1):
225 if height > 0:
226 child_ptr = node_ptr["edges"][i]["value"]["value"]
227 for child in children_of_node(child_ptr, height - 1, want_values):
228 yield child
229 if i < length:
230 if want_values:
231 yield keys[i]["value"]["value"], values[i]["value"]["value"]
232 else:
233 yield keys[i]["value"]["value"]
234
235
236class StdBTreeSetProvider:
237 def __init__(self, valobj):
238 self.valobj = valobj
239
240 def to_string(self):
241 return "BTreeSet(size={})".format(self.valobj["map"]["length"])
242
243 def children(self):
244 inner_map = self.valobj["map"]
245 if inner_map["length"] > 0:
246 root = inner_map["root"]
247 if "core::option::Option<" in root.type.name:
248 type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
249 root = root.cast(gdb.lookup_type(type_name))
250
251 node_ptr = root["node"]
252 for i, child in enumerate(children_of_node(node_ptr, root["height"], False)):
253 yield "[{}]".format(i), child
254
255 @staticmethod
256 def display_hint():
257 return "array"
258
259
260class StdBTreeMapProvider:
261 def __init__(self, valobj):
262 self.valobj = valobj
263
264 def to_string(self):
265 return "BTreeMap(size={})".format(self.valobj["length"])
266
267 def children(self):
268 if self.valobj["length"] > 0:
269 root = self.valobj["root"]
270 if "core::option::Option<" in root.type.name:
271 type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
272 root = root.cast(gdb.lookup_type(type_name))
273
274 node_ptr = root["node"]
275 for i, child in enumerate(children_of_node(node_ptr, root["height"], True)):
276 yield "key{}".format(i), child[0]
277 yield "val{}".format(i), child[1]
278
279 @staticmethod
280 def display_hint():
281 return "map"
282
283
284# BACKCOMPAT: rust 1.35
285class StdOldHashMapProvider:
286 def __init__(self, valobj, show_values=True):
287 self.valobj = valobj
288 self.show_values = show_values
289
290 self.table = self.valobj["table"]
291 self.size = int(self.table["size"])
292 self.hashes = self.table["hashes"]
293 self.hash_uint_type = self.hashes.type
294 self.hash_uint_size = self.hashes.type.sizeof
295 self.modulo = 2 ** self.hash_uint_size
296 self.data_ptr = self.hashes[ZERO_FIELD]["pointer"]
297
298 self.capacity_mask = int(self.table["capacity_mask"])
299 self.capacity = (self.capacity_mask + 1) % self.modulo
300
301 marker = self.table["marker"].type
302 self.pair_type = marker.template_argument(0)
303 self.pair_type_size = self.pair_type.sizeof
304
305 self.valid_indices = []
306 for idx in range(self.capacity):
307 data_ptr = self.data_ptr.cast(self.hash_uint_type.pointer())
308 address = data_ptr + idx
309 hash_uint = address.dereference()
310 hash_ptr = hash_uint[ZERO_FIELD]["pointer"]
311 if int(hash_ptr) != 0:
312 self.valid_indices.append(idx)
313
314 def to_string(self):
315 if self.show_values:
316 return "HashMap(size={})".format(self.size)
317 else:
318 return "HashSet(size={})".format(self.size)
319
320 def children(self):
321 start = int(self.data_ptr) & ~1
322
323 hashes = self.hash_uint_size * self.capacity
324 align = self.pair_type_size
325 len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
326 (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
327
328 pairs_offset = hashes + len_rounded_up
329 pairs_start = gdb.Value(start + pairs_offset).cast(self.pair_type.pointer())
330
331 for index in range(self.size):
332 table_index = self.valid_indices[index]
333 idx = table_index & self.capacity_mask
334 element = (pairs_start + idx).dereference()
335 if self.show_values:
336 yield "key{}".format(index), element[ZERO_FIELD]
337 yield "val{}".format(index), element[FIRST_FIELD]
338 else:
339 yield "[{}]".format(index), element[ZERO_FIELD]
340
341 def display_hint(self):
342 return "map" if self.show_values else "array"
343
344
345class StdHashMapProvider:
346 def __init__(self, valobj, show_values=True):
347 self.valobj = valobj
348 self.show_values = show_values
349
350 table = self.valobj["base"]["table"]
351 capacity = int(table["bucket_mask"]) + 1
352 ctrl = table["ctrl"]["pointer"]
353
354 self.size = int(table["items"])
3dfed10e
XL
355 self.pair_type = table.type.template_argument(0)
356
357 self.new_layout = not table.type.has_key("data")
358 if self.new_layout:
359 self.data_ptr = ctrl.cast(self.pair_type.pointer())
360 else:
361 self.data_ptr = table["data"]["pointer"]
f035d41b
XL
362
363 self.valid_indices = []
364 for idx in range(capacity):
365 address = ctrl + idx
366 value = address.dereference()
367 is_presented = value & 128 == 0
368 if is_presented:
369 self.valid_indices.append(idx)
370
371 def to_string(self):
372 if self.show_values:
373 return "HashMap(size={})".format(self.size)
374 else:
375 return "HashSet(size={})".format(self.size)
376
377 def children(self):
378 pairs_start = self.data_ptr
379
380 for index in range(self.size):
381 idx = self.valid_indices[index]
3dfed10e
XL
382 if self.new_layout:
383 idx = -(idx + 1)
f035d41b
XL
384 element = (pairs_start + idx).dereference()
385 if self.show_values:
386 yield "key{}".format(index), element[ZERO_FIELD]
387 yield "val{}".format(index), element[FIRST_FIELD]
388 else:
389 yield "[{}]".format(index), element[ZERO_FIELD]
390
391 def display_hint(self):
392 return "map" if self.show_values else "array"