I am trying to debug a very unsafe Rust code (a BTree implementation), and I notice that in GDB it is very hard to read the information from types, mostly due to it always printing the fully qualified name of the types:
(gdb) p self.root
$8 = voronoi_sweep::btree::InternalNode<voronoi_sweep::btree::test::TestItem, 3> {inner: voronoi_sweep::btree::LeafNode<voronoi_sweep::btree::test::TestItem, 3> {values: [
core::mem::maybe_uninit::MaybeUninit<voronoi_sweep::btree::test::TestItem> {uninit: (), value: core::mem::manually_drop::ManuallyDrop<voronoi_sweep::btree::test::TestItem> {value: voronoi_sweep::btree::test::TestItem (3)}},
core::mem::maybe_uninit::MaybeUninit<voronoi_sweep::btree::test::TestItem> {uninit: (), value: core::mem::manually_drop::ManuallyDrop<voronoi_sweep::btree::test::TestItem> {value: voronoi_sweep::btree::test::TestItem (32767)}},
core::mem::maybe_uninit::MaybeUninit<voronoi_sweep::btree::test::TestItem> {uninit: (), value: core::mem::manually_drop::ManuallyDrop<voronoi_sweep::btree::test::TestItem> {value: voronoi_sweep::btree::test::TestItem (32767)}}], len: 1, internal: true}, child0: core::option::Option<core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>>>::Some(core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>> {pointer: 0x7ffff0001be0}), childs: [
core::option::Option<core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>>>::Some(core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>> {pointer: 0x7ffff0001c20}),
core::option::Option<core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>>>::None,
core::option::Option<core::ptr::non_null::NonNull<voronoi_sweep::btree::Node<voronoi_sweep::btree::test::TestItem, 3>>>::None]}
It would be much nicer if it just prints the last name of each type (although is still bad due to the nested types):
$8 = InternalNode<TestItem, 3> {inner: LeafNode<TestItem, 3> {values: [
MaybeUninit<TestItem> {uninit: (), value: ManuallyDrop<TestItem> {value: TestItem (3)}},
MaybeUninit<TestItem> {uninit: (), value: ManuallyDrop<TestItem> {value: TestItem (32767)}},
MaybeUninit<TestItem> {uninit: (), value: ManuallyDrop<TestItem> {value: TestItem (32767)}}], len: 1, internal: true}, child0: Option<NonNull<Node<TestItem, 3>>>Some(NonNull<Node<TestItem, 3>> {pointer: 0x7ffff0001be0}), childs: [
Option<NonNull<Node<TestItem, 3>>>Some(NonNull<Node<TestItem, 3>> {pointer: 0x7ffff0001c20}),
Option<NonNull<Node<TestItem, 3>>>None,
Option<NonNull<Node<TestItem, 3>>>None]}
Anyone knows how can I achieve the above? I tried creating a GDB type printer in python (see Type Printing API (Debugging with GDB)), but I could not get it to work far enough to test if it would work (the type printer is instantiate
d, but regonize
is never called).
Here is my python script, if anyone is curious.
import gdb
# write log to log.txt
def log(msg):
with open("log.txt", "a") as f:
f.write(msg + "\n")
class RustTypePrinter(gdb.types.TypePrinter):
def __init__(self, name):
self.name = name
self.enabled = True
def instantiate(self):
log("Instantiate")
return RustTypeRecognizer()
class RustTypeRecognizer:
def __init__(self):
log("Init RustTypeRecognizer")
self.enabled = True
def recognize(self, type):
log("Recognize")
return type.name.split("::")[-1]
x = RustTypePrinter("RussTypePrinter")
gdb.types.register_type_printer(gdb.current_objfile(), x)