about summary refs log tree commit diff
path: root/src/etc/gdb_lookup.py
diff options
context:
space:
mode:
authorortem <ortem00@gmail.com>2019-05-14 15:50:58 +0300
committerortem <ortem00@gmail.com>2020-06-09 16:13:11 +0300
commit47c26e69a986d25ed9d26aebc2787334956a89ae (patch)
tree66fd9f4f34dbcc2d4bd21068c49041d50d05eca4 /src/etc/gdb_lookup.py
parenta9ca1ec9280ca1e5020edd699917c3367a30a798 (diff)
downloadrust-47c26e69a986d25ed9d26aebc2787334956a89ae.tar.gz
rust-47c26e69a986d25ed9d26aebc2787334956a89ae.zip
Implement new gdb/lldb pretty-printers
Replace old GDB and LLDB pretty-printers with new ones
which were originally written for IntelliJ Rust.
New LLDB pretty-printers support synthetic children.
New GDB/LLDB pretty-printers support all Rust types
supported by old pretty-printers, and also support:
Rc, Arc, Cell, Ref, RefCell, RefMut, HashMap, HashSet.
Diffstat (limited to 'src/etc/gdb_lookup.py')
-rw-r--r--src/etc/gdb_lookup.py92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py
new file mode 100644
index 00000000000..2a46eaadad6
--- /dev/null
+++ b/src/etc/gdb_lookup.py
@@ -0,0 +1,92 @@
+import gdb
+import re
+
+from gdb_providers import *
+from rust_types import *
+
+
+rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True)
+_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
+gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
+
+def register_printers(objfile):
+    objfile.pretty_printers.append(lookup)
+
+
+# BACKCOMPAT: rust 1.35
+def is_hashbrown_hashmap(hash_map):
+    return len(hash_map.type.fields()) == 1
+
+
+def classify_rust_type(type):
+    type_class = type.code
+    if type_class == gdb.TYPE_CODE_STRUCT:
+        return classify_struct(type.tag, type.fields())
+    if type_class == gdb.TYPE_CODE_UNION:
+        return classify_union(type.fields())
+
+    return RustType.OTHER
+
+
+def check_enum_discriminant(valobj):
+    content = valobj[valobj.type.fields()[0]]
+    fields = content.type.fields()
+    if len(fields) > 1:
+        discriminant = int(content[fields[0]]) + 1
+        if discriminant > len(fields):
+            # invalid discriminant
+            return False
+    return True
+
+
+def lookup(valobj):
+    rust_type = classify_rust_type(valobj.type)
+
+    if rust_type == RustType.ENUM:
+        # use enum provider only for GDB <7.12
+        if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12):
+            if check_enum_discriminant(valobj):
+                return EnumProvider(valobj)
+
+    if rust_type == RustType.STD_STRING:
+        return StdStringProvider(valobj)
+    if rust_type == RustType.STD_OS_STRING:
+        return StdOsStringProvider(valobj)
+    if rust_type == RustType.STD_STR and not rust_enabled:
+        return StdStrProvider(valobj)
+
+    if rust_type == RustType.STD_VEC:
+        return StdVecProvider(valobj)
+    if rust_type == RustType.STD_VEC_DEQUE:
+        return StdVecDequeProvider(valobj)
+    if rust_type == RustType.STD_BTREE_SET:
+        return StdBTreeSetProvider(valobj)
+    if rust_type == RustType.STD_BTREE_MAP:
+        return StdBTreeMapProvider(valobj)
+    if rust_type == RustType.STD_HASH_MAP:
+        if is_hashbrown_hashmap(valobj):
+            return StdHashMapProvider(valobj)
+        else:
+            return StdOldHashMapProvider(valobj)
+    if rust_type == RustType.STD_HASH_SET:
+        hash_map = valobj["map"]
+        if is_hashbrown_hashmap(hash_map):
+            return StdHashMapProvider(hash_map, show_values=False)
+        else:
+            return StdOldHashMapProvider(hash_map, show_values=False)
+
+    if rust_type == RustType.STD_RC:
+        return StdRcProvider(valobj)
+    if rust_type == RustType.STD_ARC:
+        return StdRcProvider(valobj, is_atomic=True)
+
+    if rust_type == RustType.STD_CELL:
+        return StdCellProvider(valobj)
+    if rust_type == RustType.STD_REF:
+        return StdRefProvider(valobj)
+    if rust_type == RustType.STD_REF_MUT:
+        return StdRefProvider(valobj)
+    if rust_type == RustType.STD_REF_CELL:
+        return StdRefCellProvider(valobj)
+
+    return None