1 from sys import version_info
5 if version_info[0] >= 3:
12 def unwrap_unique_or_non_null(unique_or_nonnull):
13 # BACKCOMPAT: rust 1.32
14 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
15 # BACKCOMPAT: rust 1.60
16 # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
17 ptr = unique_or_nonnull["pointer"]
18 return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]]
22 def __init__(self, valobj):
23 content = valobj[valobj.type.fields()[0]]
24 fields = content.type.fields()
25 self.empty = len(fields) == 0
30 discriminant = int(content[fields[0]]) + 1
31 self.active_variant = content[fields[discriminant]]
32 self.name = fields[discriminant].name
33 self.full_name = "{}::{}".format(valobj.type.name, self.name)
35 self.full_name = valobj.type.name
42 yield self.name, self.active_variant
45 class StdStringProvider:
46 def __init__(self, valobj):
49 self.length = int(vec["len"])
50 self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
53 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
60 class StdOsStringProvider:
61 def __init__(self, valobj):
63 buf = self.valobj["inner"]["inner"]
64 is_windows = "Wtf8Buf" in buf.type.name
65 vec = buf[ZERO_FIELD] if is_windows else buf
67 self.length = int(vec["len"])
68 self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
71 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
73 def display_hint(self):
78 def __init__(self, valobj):
80 self.length = int(valobj["length"])
81 self.data_ptr = valobj["data_ptr"]
84 return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
90 def _enumerate_array_elements(element_ptrs):
91 for (i, element_ptr) in enumerate(element_ptrs):
92 key = "[{}]".format(i)
93 element = element_ptr.dereference()
96 # rust-lang/rust#64343: passing deref expr to `str` allows
97 # catching exception on garbage pointer
100 yield key, "inaccessible"
106 class StdSliceProvider:
107 def __init__(self, valobj):
109 self.length = int(valobj["length"])
110 self.data_ptr = valobj["data_ptr"]
113 return "{}(size={})".format(self.valobj.type, self.length)
116 return _enumerate_array_elements(
117 self.data_ptr + index for index in xrange(self.length)
124 class StdVecProvider:
125 def __init__(self, valobj):
127 self.length = int(valobj["len"])
128 self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
131 return "Vec(size={})".format(self.length)
134 return _enumerate_array_elements(
135 self.data_ptr + index for index in xrange(self.length)
143 class StdVecDequeProvider:
144 def __init__(self, valobj):
146 self.head = int(valobj["head"])
147 self.tail = int(valobj["tail"])
148 self.cap = int(valobj["buf"]["cap"])
149 self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
150 if self.head >= self.tail:
151 self.size = self.head - self.tail
153 self.size = self.cap + self.head - self.tail
156 return "VecDeque(size={})".format(self.size)
159 return _enumerate_array_elements(
160 (self.data_ptr + ((self.tail + index) % self.cap)) for index in xrange(self.size)
169 def __init__(self, valobj, is_atomic=False):
171 self.is_atomic = is_atomic
172 self.ptr = unwrap_unique_or_non_null(valobj["ptr"])
173 self.value = self.ptr["data" if is_atomic else "value"]
174 self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"]
175 self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"] - 1
179 return "Arc(strong={}, weak={})".format(int(self.strong), int(self.weak))
181 return "Rc(strong={}, weak={})".format(int(self.strong), int(self.weak))
184 yield "value", self.value
185 yield "strong", self.strong
186 yield "weak", self.weak
189 class StdCellProvider:
190 def __init__(self, valobj):
191 self.value = valobj["value"]["value"]
197 yield "value", self.value
200 class StdRefProvider:
201 def __init__(self, valobj):
202 self.value = valobj["value"].dereference()
203 self.borrow = valobj["borrow"]["borrow"]["value"]["value"]
206 borrow = int(self.borrow)
208 return "Ref(borrow={})".format(borrow)
210 return "Ref(borrow_mut={})".format(-borrow)
213 yield "*value", self.value
214 yield "borrow", self.borrow
217 class StdRefCellProvider:
218 def __init__(self, valobj):
219 self.value = valobj["value"]["value"]
220 self.borrow = valobj["borrow"]["value"]["value"]
223 borrow = int(self.borrow)
225 return "RefCell(borrow={})".format(borrow)
227 return "RefCell(borrow_mut={})".format(-borrow)
230 yield "value", self.value
231 yield "borrow", self.borrow
234 class StdNonZeroNumberProvider:
235 def __init__(self, valobj):
236 fields = valobj.type.fields()
237 assert len(fields) == 1
238 field = list(fields)[0]
239 self.value = str(valobj[field.name])
245 # Yields children (in a provider's sense of the word) for a BTreeMap.
246 def children_of_btree_map(map):
247 # Yields each key/value pair in the node and in any child nodes.
248 def children_of_node(node_ptr, height):
249 def cast_to_internal(node):
250 internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
251 internal_type = gdb.lookup_type(internal_type_name)
252 return node.cast(internal_type.pointer())
254 if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"):
255 # BACKCOMPAT: rust 1.49
256 node_ptr = node_ptr["ptr"]
257 node_ptr = unwrap_unique_or_non_null(node_ptr)
258 leaf = node_ptr.dereference()
261 edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
264 for i in xrange(0, length + 1):
266 child_ptr = edges[i]["value"]["value"]
267 for child in children_of_node(child_ptr, height - 1):
270 # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
271 key_type_size = keys.type.sizeof
272 val_type_size = vals.type.sizeof
273 key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()")
274 val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()")
277 if map["length"] > 0:
279 if root.type.name.startswith("core::option::Option<"):
280 root = root.cast(gdb.lookup_type(root.type.name[21:-1]))
281 node_ptr = root["node"]
282 height = root["height"]
283 for child in children_of_node(node_ptr, height):
287 class StdBTreeSetProvider:
288 def __init__(self, valobj):
292 return "BTreeSet(size={})".format(self.valobj["map"]["length"])
295 inner_map = self.valobj["map"]
296 for i, (child, _) in enumerate(children_of_btree_map(inner_map)):
297 yield "[{}]".format(i), child
304 class StdBTreeMapProvider:
305 def __init__(self, valobj):
309 return "BTreeMap(size={})".format(self.valobj["length"])
312 for i, (key, val) in enumerate(children_of_btree_map(self.valobj)):
313 yield "key{}".format(i), key
314 yield "val{}".format(i), val
321 # BACKCOMPAT: rust 1.35
322 class StdOldHashMapProvider:
323 def __init__(self, valobj, show_values=True):
325 self.show_values = show_values
327 self.table = self.valobj["table"]
328 self.size = int(self.table["size"])
329 self.hashes = self.table["hashes"]
330 self.hash_uint_type = self.hashes.type
331 self.hash_uint_size = self.hashes.type.sizeof
332 self.modulo = 2 ** self.hash_uint_size
333 self.data_ptr = self.hashes[ZERO_FIELD]["pointer"]
335 self.capacity_mask = int(self.table["capacity_mask"])
336 self.capacity = (self.capacity_mask + 1) % self.modulo
338 marker = self.table["marker"].type
339 self.pair_type = marker.template_argument(0)
340 self.pair_type_size = self.pair_type.sizeof
342 self.valid_indices = []
343 for idx in range(self.capacity):
344 data_ptr = self.data_ptr.cast(self.hash_uint_type.pointer())
345 address = data_ptr + idx
346 hash_uint = address.dereference()
347 hash_ptr = hash_uint[ZERO_FIELD]["pointer"]
348 if int(hash_ptr) != 0:
349 self.valid_indices.append(idx)
353 return "HashMap(size={})".format(self.size)
355 return "HashSet(size={})".format(self.size)
358 start = int(self.data_ptr) & ~1
360 hashes = self.hash_uint_size * self.capacity
361 align = self.pair_type_size
362 len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
363 (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
365 pairs_offset = hashes + len_rounded_up
366 pairs_start = gdb.Value(start + pairs_offset).cast(self.pair_type.pointer())
368 for index in range(self.size):
369 table_index = self.valid_indices[index]
370 idx = table_index & self.capacity_mask
371 element = (pairs_start + idx).dereference()
373 yield "key{}".format(index), element[ZERO_FIELD]
374 yield "val{}".format(index), element[FIRST_FIELD]
376 yield "[{}]".format(index), element[ZERO_FIELD]
378 def display_hint(self):
379 return "map" if self.show_values else "array"
382 class StdHashMapProvider:
383 def __init__(self, valobj, show_values=True):
385 self.show_values = show_values
388 table_inner = table["table"]
389 capacity = int(table_inner["bucket_mask"]) + 1
390 ctrl = table_inner["ctrl"]["pointer"]
392 self.size = int(table_inner["items"])
393 self.pair_type = table.type.template_argument(0).strip_typedefs()
395 self.new_layout = not table_inner.type.has_key("data")
397 self.data_ptr = ctrl.cast(self.pair_type.pointer())
399 self.data_ptr = table_inner["data"]["pointer"]
401 self.valid_indices = []
402 for idx in range(capacity):
404 value = address.dereference()
405 is_presented = value & 128 == 0
407 self.valid_indices.append(idx)
411 hashbrown_hashmap = self.valobj["base"]
412 elif self.valobj.type.fields()[0].name == "map":
413 # BACKCOMPAT: rust 1.47
414 # HashSet wraps std::collections::HashMap, which wraps hashbrown::HashMap
415 hashbrown_hashmap = self.valobj["map"]["base"]
417 # HashSet wraps hashbrown::HashSet, which wraps hashbrown::HashMap
418 hashbrown_hashmap = self.valobj["base"]["map"]
419 return hashbrown_hashmap["table"]
423 return "HashMap(size={})".format(self.size)
425 return "HashSet(size={})".format(self.size)
428 pairs_start = self.data_ptr
430 for index in range(self.size):
431 idx = self.valid_indices[index]
434 element = (pairs_start + idx).dereference()
436 yield "key{}".format(index), element[ZERO_FIELD]
437 yield "val{}".format(index), element[FIRST_FIELD]
439 yield "[{}]".format(index), element[ZERO_FIELD]
441 def display_hint(self):
442 return "map" if self.show_values else "array"