diff options
| author | ortem <ortem00@gmail.com> | 2019-05-14 15:50:58 +0300 |
|---|---|---|
| committer | ortem <ortem00@gmail.com> | 2020-06-09 16:13:11 +0300 |
| commit | 47c26e69a986d25ed9d26aebc2787334956a89ae (patch) | |
| tree | 66fd9f4f34dbcc2d4bd21068c49041d50d05eca4 /src/etc/gdb_lookup.py | |
| parent | a9ca1ec9280ca1e5020edd699917c3367a30a798 (diff) | |
| download | rust-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.py | 92 |
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 |
