From e98beb5aeb74371cd03c7aed8e8427dc4a65ce1f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 20 Oct 2023 08:35:09 -0600 Subject: [PATCH] Rewrite gdb pretty-printer registration Currently, the Rust pretty-printers are registered in gdb using the uninformative name "lookup": (gdb) info pretty-printer global pretty-printers: [...] objfile /home/tromey/[...] lookup It's nicer for users if the top-level registration is given a clear name. Additionally, gdb lets users individually enable and disable specific printers, provided they are registered correctly. This patch implements both these ideas. Now the output looks like: (gdb) info pretty-printer global pretty-printers: [...] objfile /home/tromey/[...] rust StdArc StdBTreeMap StdBTreeSet StdCell StdHashMap StdHashSet StdNonZeroNumber StdOsString StdRc StdRef StdRefCell StdRefMut StdSlice StdStr StdString StdVec StdVecDeque --- src/etc/gdb_lookup.py | 133 +++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py index 8171cb4e9a68a..f3ac9c1097806 100644 --- a/src/etc/gdb_lookup.py +++ b/src/etc/gdb_lookup.py @@ -1,4 +1,5 @@ import gdb +import gdb.printing import re from gdb_providers import * @@ -9,7 +10,7 @@ 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) + objfile.pretty_printers.append(printer) # BACKCOMPAT: rust 1.35 @@ -38,58 +39,80 @@ def check_enum_discriminant(valobj): 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: - return StdStrProvider(valobj) - if rust_type == RustType.STD_SLICE: - return StdSliceProvider(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[valobj.type.fields()[0]] - if is_hashbrown_hashmap(hash_map): - return StdHashMapProvider(valobj, 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) - - if rust_type == RustType.STD_NONZERO_NUMBER: - return StdNonZeroNumberProvider(valobj) - +# Helper for enum printing that checks the discriminant. Only used in +# older gdb. +def enum_provider(valobj): + if check_enum_discriminant(valobj): + return EnumProvider(valobj) return None + + +# Helper to handle both old and new hash maps. +def hashmap_provider(valobj): + if is_hashbrown_hashmap(valobj): + return StdHashMapProvider(valobj) + else: + return StdOldHashMapProvider(valobj) + + +# Helper to handle both old and new hash sets. +def hashset_provider(valobj): + hash_map = valobj[valobj.type.fields()[0]] + if is_hashbrown_hashmap(hash_map): + return StdHashMapProvider(valobj, show_values=False) + else: + return StdOldHashMapProvider(hash_map, show_values=False) + + +class PrintByRustType(gdb.printing.SubPrettyPrinter): + def __init__(self, name, provider): + super(PrintByRustType, self).__init__(name) + self.provider = provider + + def __call__(self, val): + if self.enabled: + return self.provider(val) + return None + + +class RustPrettyPrinter(gdb.printing.PrettyPrinter): + def __init__(self, name): + super(RustPrettyPrinter, self).__init__(name, []) + self.type_map = {} + + def add(self, rust_type, provider): + # Just use the rust_type as the name. + printer = PrintByRustType(rust_type, provider) + self.type_map[rust_type] = printer + self.subprinters.append(printer) + + def __call__(self, valobj): + rust_type = classify_rust_type(valobj.type) + if rust_type in self.type_map: + return self.type_map[rust_type](valobj) + return None + + +printer = RustPrettyPrinter("rust") +# use enum provider only for GDB <7.12 +if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12): + printer.add(RustType.ENUM, enum_provider) +printer.add(RustType.STD_STRING, StdStringProvider) +printer.add(RustType.STD_OS_STRING, StdOsStringProvider) +printer.add(RustType.STD_STR, StdStrProvider) +printer.add(RustType.STD_SLICE, StdSliceProvider) +printer.add(RustType.STD_VEC, StdVecProvider) +printer.add(RustType.STD_VEC_DEQUE, StdVecDequeProvider) +printer.add(RustType.STD_BTREE_SET, StdBTreeSetProvider) +printer.add(RustType.STD_BTREE_MAP, StdBTreeMapProvider) +printer.add(RustType.STD_HASH_MAP, hashmap_provider) +printer.add(RustType.STD_HASH_SET, hashset_provider) +printer.add(RustType.STD_RC, StdRcProvider) +printer.add(RustType.STD_ARC, lambda valobj: StdRcProvider(valobj, is_atomic=True)) + +printer.add(RustType.STD_CELL, StdCellProvider) +printer.add(RustType.STD_REF, StdRefProvider) +printer.add(RustType.STD_REF_MUT, StdRefProvider) +printer.add(RustType.STD_REF_CELL, StdRefCellProvider) + +printer.add(RustType.STD_NONZERO_NUMBER, StdNonZeroNumberProvider)