about summary refs log tree commit diff
path: root/src/etc/gdb_providers.py
diff options
context:
space:
mode:
authorStein Somers <git@steinsomers.be>2020-10-08 22:15:18 +0200
committerStein Somers <git@steinsomers.be>2020-10-10 15:27:51 +0200
commitbb9da7a0edc60991e14b7e8c738e5d8ae3661512 (patch)
treebeac1ed0a9e67f68954ffb680a105717754ae278 /src/etc/gdb_providers.py
parentefbaa413061c2a6e52f06f00a60ee7830fcf3ea5 (diff)
downloadrust-bb9da7a0edc60991e14b7e8c738e5d8ae3661512.tar.gz
rust-bb9da7a0edc60991e14b7e8c738e5d8ae3661512.zip
BTreeMap: fix gdb introspection of BTreeMap with ZST keys or values
Diffstat (limited to 'src/etc/gdb_providers.py')
-rw-r--r--src/etc/gdb_providers.py63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index bae51e6f9ee..b2d343fd7af 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -207,30 +207,46 @@ class StdRefCellProvider:
         yield "borrow", self.borrow
 
 
-# Yield each key (and optionally value) from a BoxedNode.
-def children_of_node(boxed_node, height, want_values):
+# Yields children (in a provider's sense of the word) for a tree headed by a BoxedNode.
+# In particular, yields each key/value pair in the node and in any child nodes.
+def children_of_node(boxed_node, height):
     def cast_to_internal(node):
-        internal_type_name = str(node.type.target()).replace("LeafNode", "InternalNode", 1)
+        internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
         internal_type = lookup_type(internal_type_name)
         return node.cast(internal_type.pointer())
 
     node_ptr = unwrap_unique_or_non_null(boxed_node["ptr"])
-    node_ptr = cast_to_internal(node_ptr) if height > 0 else node_ptr
-    leaf = node_ptr["data"] if height > 0 else node_ptr.dereference()
+    leaf = node_ptr.dereference()
     keys = leaf["keys"]
-    values = leaf["vals"]
+    vals = leaf["vals"]
+    edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
     length = int(leaf["len"])
 
     for i in xrange(0, length + 1):
         if height > 0:
-            child_ptr = node_ptr["edges"][i]["value"]["value"]
-            for child in children_of_node(child_ptr, height - 1, want_values):
+            boxed_child_node = edges[i]["value"]["value"]
+            for child in children_of_node(boxed_child_node, height - 1):
                 yield child
         if i < length:
-            if want_values:
-                yield keys[i]["value"]["value"], values[i]["value"]["value"]
-            else:
-                yield keys[i]["value"]["value"]
+            # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
+            key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else None
+            val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else None
+            yield key, val
+
+
+# Yields children for a BTreeMap.
+def children_of_map(map):
+    if map["length"] > 0:
+        root = map["root"]
+        if root.type.name.startswith("core::option::Option<"):
+            root = root.cast(gdb.lookup_type(root.type.name[21:-1]))
+        boxed_root_node = root["node"]
+        height = root["height"]
+        for i, (key, val) in enumerate(children_of_node(boxed_root_node, height)):
+            if key is not None:
+                yield "key{}".format(i), key
+            if val is not None:
+                yield "val{}".format(i), val
 
 
 class StdBTreeSetProvider:
@@ -242,15 +258,8 @@ class StdBTreeSetProvider:
 
     def children(self):
         inner_map = self.valobj["map"]
-        if inner_map["length"] > 0:
-            root = inner_map["root"]
-            if "core::option::Option<" in root.type.name:
-                type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
-                root = root.cast(gdb.lookup_type(type_name))
-
-            node_ptr = root["node"]
-            for i, child in enumerate(children_of_node(node_ptr, root["height"], False)):
-                yield "[{}]".format(i), child
+        for child in children_of_map(inner_map):
+            yield child
 
     @staticmethod
     def display_hint():
@@ -265,16 +274,8 @@ class StdBTreeMapProvider:
         return "BTreeMap(size={})".format(self.valobj["length"])
 
     def children(self):
-        if self.valobj["length"] > 0:
-            root = self.valobj["root"]
-            if "core::option::Option<" in root.type.name:
-                type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
-                root = root.cast(gdb.lookup_type(type_name))
-
-            node_ptr = root["node"]
-            for i, child in enumerate(children_of_node(node_ptr, root["height"], True)):
-                yield "key{}".format(i), child[0]
-                yield "val{}".format(i), child[1]
+        for child in children_of_map(self.valobj):
+            yield child
 
     @staticmethod
     def display_hint():