From 4ff7553d6b918e4eef643d10bd8f41492355f39c Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 16 Mar 2022 18:13:10 +0100 Subject: [PATCH] gdb: restructure pretty printers into different files --- tools/stage1_gdb_pretty_printers.py | 37 +++ tools/stage2_gdb_pretty_printers.py | 189 ++++++++++++++ tools/std_gdb_pretty_printers.py | 142 ++++++++++ tools/zig-gdb.py | 389 ---------------------------- tools/zig_gdb_pretty_printers.py | 4 +- 5 files changed, 370 insertions(+), 391 deletions(-) create mode 100644 tools/stage1_gdb_pretty_printers.py create mode 100644 tools/stage2_gdb_pretty_printers.py create mode 100644 tools/std_gdb_pretty_printers.py delete mode 100644 tools/zig-gdb.py diff --git a/tools/stage1_gdb_pretty_printers.py b/tools/stage1_gdb_pretty_printers.py new file mode 100644 index 0000000000..64eb27f25e --- /dev/null +++ b/tools/stage1_gdb_pretty_printers.py @@ -0,0 +1,37 @@ +# pretty printing for stage1. +# put "source /path/to/stage1_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically. +import gdb.printing + +class ZigListPrinter: + def __init__(self, val): + self.val = val + + def to_string(self): + return '%s of length %d, capacity %d' % (self.val.type.name, int(self.val['length']), int(self.val['capacity'])) + + def children(self): + def it(ziglist): + for i in range(int(ziglist.val['length'])): + item = ziglist.val['items'] + i + yield ('[%d]' % i, item.dereference()) + return it(self) + + def display_hint(self): + return 'array' + +# handle both Buf and ZigList because Buf* doesn't work otherwise (gdb bug?) +class BufPrinter: + def __init__(self, val): + self.val = val['list'] if val.type.name == 'Buf' else val + + def to_string(self): + return self.val['items'].string(length=int(self.val['length'])) + + def display_hint(self): + return 'string' + +pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler') +pp.add_printer('Buf', '^Buf$', BufPrinter) +pp.add_printer('ZigList', '^ZigList$', BufPrinter) +pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter) +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) diff --git a/tools/stage2_gdb_pretty_printers.py b/tools/stage2_gdb_pretty_printers.py new file mode 100644 index 0000000000..db91fc172d --- /dev/null +++ b/tools/stage2_gdb_pretty_printers.py @@ -0,0 +1,189 @@ +# pretty printing for stage 2. +# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically. +import re +import gdb.printing + +class TypePrinter: + no_payload_count = 4096 + + # Keep in sync with src/type.zig + # Types which have no payload do not need to be entered here. + payload_type_names = { + 'array_u8': 'type.Len', + 'array_u8_sentinel_0': 'Len', + + 'single_const_pointer': 'ElemType', + 'single_mut_pointer': 'ElemType', + 'many_const_pointer': 'ElemType', + 'many_mut_pointer': 'ElemType', + 'c_const_pointer': 'ElemType', + 'c_mut_pointer': 'ElemType', + 'const_slice': 'ElemType', + 'mut_slice': 'ElemType', + 'optional': 'ElemType', + 'optional_single_mut_pointer': 'ElemType', + 'optional_single_const_pointer': 'ElemType', + 'anyframe_T': 'ElemType', + + 'int_signed': 'Bits', + 'int_unsigned': 'Bits', + + 'error_set': 'ErrorSet', + 'error_set_inferred': 'ErrorSetInferred', + 'error_set_merged': 'ErrorSetMerged', + + 'array': 'Array', + 'vector': 'Array', + + 'array_sentinel': 'ArraySentinel', + 'pointer': 'Pointer', + 'function': 'Function', + 'error_union': 'ErrorUnion', + 'error_set_single': 'Name', + 'opaque': 'Opaque', + 'struct': 'Struct', + 'union': 'Union', + 'union_tagged': 'Union', + 'enum_full, .enum_nonexhaustive': 'EnumFull', + 'enum_simple': 'EnumSimple', + 'enum_numbered': 'EnumNumbered', + 'empty_struct': 'ContainerScope', + 'tuple': 'Tuple', + 'anon_struct': 'AnonStruct', + } + + def __init__(self, val): + self.val = val + + def tag(self): + tag_if_small_enough = self.val['tag_if_small_enough'] + tag_type = tag_if_small_enough.type + + if tag_if_small_enough < TypePrinter.no_payload_count: + return tag_if_small_enough + else: + return self.val['ptr_otherwise'].dereference()['tag'] + + def payload_type(self): + tag = self.tag() + if tag is None: + return None + + type_name = TypePrinter.payload_type_names.get(str(tag)) + if type_name is None: + return None + return gdb.lookup_type('struct type.%s' % type_name) + + def to_string(self): + tag = self.tag() + if tag is None: + return '(invalid type)' + if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count: + return '.%s' % str(tag) + return None + + def children(self): + if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count: + return + + yield ('tag', '.%s' % str(self.tag())) + + payload_type = self.payload_type() + if payload_type is not None: + yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) + +class ValuePrinter: + no_payload_count = 4096 + + # Keep in sync with src/value.zig + # Values which have no payload do not need to be entered here. + payload_type_names = { + 'big_int_positive': 'BigInt', + 'big_int_negative': 'BigInt', + + 'extern_fn': 'ExternFn', + + 'decl_ref': 'Decl', + + 'repeated': 'SubValue', + 'eu_payload': 'SubValue', + 'opt_payload': 'SubValue', + 'empty_array_sentinel': 'SubValue', + + 'eu_payload_ptr': 'PayloadPtr', + 'opt_payload_ptr': 'PayloadPtr', + + 'bytes': 'Bytes', + 'enum_literal': 'Bytes', + + 'slice': 'Slice', + + 'enum_field_index': 'U32', + + 'ty': 'Ty', + 'int_type': 'IntType', + 'int_u64': 'U64', + 'int_i64': 'I64', + 'function': 'Function', + 'variable': 'Variable', + 'decl_ref_mut': 'DeclRefMut', + 'elem_ptr': 'ElemPtr', + 'field_ptr': 'FieldPtr', + 'float_16': 'Float_16', + 'float_32': 'Float_32', + 'float_64': 'Float_64', + 'float_80': 'Float_80', + 'float_128': 'Float_128', + 'error': 'Error', + 'inferred_alloc': 'InferredAlloc', + 'inferred_alloc_comptime': 'InferredAllocComptime', + 'aggregate': 'Aggregate', + 'union': 'Union', + 'bound_fn': 'BoundFn', + } + + def __init__(self, val): + self.val = val + + def tag(self): + tag_if_small_enough = self.val['tag_if_small_enough'] + tag_type = tag_if_small_enough.type + + if tag_if_small_enough < ValuePrinter.no_payload_count: + return tag_if_small_enough + else: + return self.val['ptr_otherwise'].dereference()['tag'] + + def payload_type(self): + tag = self.tag() + if tag is None: + return None + + type_name = ValuePrinter.payload_type_names.get(str(tag)) + if type_name is None: + return None + return gdb.lookup_type('struct value.%s' % type_name) + + def to_string(self): + tag = self.tag() + if tag is None: + return '(invalid value)' + if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: + return '.%s' % str(tag) + return None + + def children(self): + if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: + return + + yield ('tag', '.%s' % str(self.tag())) + + payload_type = self.payload_type() + if payload_type is not None: + yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) + +pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage2 compiler') +pp.add_printer('Type', r'^type\.Type$', TypePrinter) +pp.add_printer('Value', r'^value\.Value$', ValuePrinter) +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) + diff --git a/tools/std_gdb_pretty_printers.py b/tools/std_gdb_pretty_printers.py new file mode 100644 index 0000000000..c89de56fa6 --- /dev/null +++ b/tools/std_gdb_pretty_printers.py @@ -0,0 +1,142 @@ +# pretty printing for the standard library. +# put "source /path/to/stage2_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically. +import re +import gdb.printing + +# Handles both ArrayList and ArrayListUnmanaged. +class ArrayListPrinter: + def __init__(self, val): + self.val = val + + def to_string(self): + type = self.val.type.name[len('std.array_list.'):] + type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type) + return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity']) + + def children(self): + for i in range(self.val['items']['len']): + item = self.val['items']['ptr'] + i + yield ('[%d]' % i, item.dereference()) + + def display_hint(self): + return 'array' + +class MultiArrayListPrinter: + def __init__(self, val): + self.val = val + + def child_type(self): + (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name) + return helper_fn.type.fields()[1].type.target() + + def to_string(self): + type = self.val.type.name[len('std.multi_array_list.'):] + return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity']) + + def slice(self): + fields = self.child_type().fields() + base = self.val['bytes'] + cap = self.val['capacity'] + len = self.val['len'] + + if len == 0: + return + + fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True) + + for field in fields: + ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1)) + base += field.type.sizeof * cap + yield (field.name, ptr) + + def children(self): + for i, (name, ptr) in enumerate(self.slice()): + yield ('[%d]' % i, name) + yield ('[%d]' % i, ptr) + + def display_hint(self): + return 'map' + +# Handles both HashMap and HashMapUnmanaged. +class HashMapPrinter: + def __init__(self, val): + self.type = val.type + is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name) + self.val = val['unmanaged'] if is_managed else val + + def header_ptr_type(self): + (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name) + return helper_fn.type.fields()[1].type + + def header(self): + if self.val['metadata'] == 0: + return None + return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference() + + def to_string(self): + type = self.type.name[len('std.hash_map.'):] + type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type) + hdr = self.header() + if hdr is not None: + cap = hdr['capacity'] + else: + cap = 0 + return '%s of length %s, capacity %s' % (type, self.val['size'], cap) + + def children(self): + hdr = self.header() + if hdr is None: + return + is_map = self.display_hint() == 'map' + for i in range(hdr['capacity']): + metadata = self.val['metadata'] + i + if metadata.dereference()['used'] == 1: + yield ('[%d]' % i, (hdr['keys'] + i).dereference()) + if is_map: + yield ('[%d]' % i, (hdr['values'] + i).dereference()) + + def display_hint(self): + for field in self.header_ptr_type().target().fields(): + if field.name == 'values': + return 'map' + return 'array' + +# Handles both ArrayHashMap and ArrayHashMapUnmanaged. +class ArrayHashMapPrinter: + def __init__(self, val): + self.type = val.type + is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name) + self.val = val['unmanaged'] if is_managed else val + + def to_string(self): + type = self.type.name[len('std.array_hash_map.'):] + type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type) + return '%s of length %s' % (type, self.val['entries']['len']) + + def children(self): + entries = MultiArrayListPrinter(self.val['entries']) + len = self.val['entries']['len'] + fields = {} + for name, ptr in entries.slice(): + fields[str(name)] = ptr + + for i in range(len): + if 'key' in fields: + yield ('[%d]' % i, fields['key'][i]) + else: + yield ('[%d]' % i, '{}') + if 'value' in fields: + yield ('[%d]' % i, fields['value'][i]) + + def display_hint(self): + for name, ptr in MultiArrayListPrinter(self.val['entries']).slice(): + if name == 'value': + return 'map' + return 'array' + +pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library') +pp.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter) +pp.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter) +pp.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter) +pp.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter) +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) diff --git a/tools/zig-gdb.py b/tools/zig-gdb.py deleted file mode 100644 index 001211267c..0000000000 --- a/tools/zig-gdb.py +++ /dev/null @@ -1,389 +0,0 @@ -# pretty printing for stage1, stage2 and the standard library -# put "source /path/to/zig-gdb.py" in ~/.gdbinit to load it automatically - -import re -import gdb.printing -import gdb.types - -class ZigListPrinter: - def __init__(self, val): - self.val = val - - def to_string(self): - return '%s of length %d, capacity %d' % (self.val.type.name, int(self.val['length']), int(self.val['capacity'])) - - def children(self): - def it(ziglist): - for i in range(int(ziglist.val['length'])): - item = ziglist.val['items'] + i - yield ('[%d]' % i, item.dereference()) - return it(self) - - def display_hint(self): - return 'array' - -# handle both Buf and ZigList because Buf* doesn't work otherwise (gdb bug?) -class BufPrinter: - def __init__(self, val): - self.val = val['list'] if val.type.name == 'Buf' else val - - def to_string(self): - return self.val['items'].string(length=int(self.val['length'])) - - def display_hint(self): - return 'string' - -class SlicePrinter: - def __init__(self, val): - self.val = val - - def children(self): - for i in range(self.val['len']): - yield ('[%d]' % i, (self.val['ptr'] + i).dereference()) - - def display_hint(self): - return 'array' - -class SliceStringPrinter: - def __init__(self, val): - self.val = val - - def to_string(self): - return self.val['ptr'].string(length=self.val['len']) - - def display_hint(self): - return 'string' - -# Handles both ArrayList and ArrayListUnmanaged. -class ArrayListPrinter: - def __init__(self, val): - self.val = val - - def to_string(self): - type = self.val.type.name[len('std.array_list.'):] - type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type) - return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity']) - - def children(self): - for i in range(self.val['items']['len']): - item = self.val['items']['ptr'] + i - yield ('[%d]' % i, item.dereference()) - - def display_hint(self): - return 'array' - -class MultiArrayListPrinter: - def __init__(self, val): - self.val = val - - def child_type(self): - (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name) - return helper_fn.type.fields()[1].type.target() - - def to_string(self): - type = self.val.type.name[len('std.multi_array_list.'):] - return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity']) - - def slice(self): - fields = self.child_type().fields() - base = self.val['bytes'] - cap = self.val['capacity'] - len = self.val['len'] - - if len == 0: - return - - fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True) - - for field in fields: - ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1)) - base += field.type.sizeof * cap - yield (field.name, ptr) - - def children(self): - for i, (name, ptr) in enumerate(self.slice()): - yield ('[%d]' % i, name) - yield ('[%d]' % i, ptr) - - def display_hint(self): - return 'map' - -# Handles both HashMap and HashMapUnmanaged. -class HashMapPrinter: - def __init__(self, val): - self.type = val.type - is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name) - self.val = val['unmanaged'] if is_managed else val - - def header_ptr_type(self): - (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name) - return helper_fn.type.fields()[1].type - - def header(self): - if self.val['metadata'] == 0: - return None - return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference() - - def to_string(self): - type = self.type.name[len('std.hash_map.'):] - type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type) - hdr = self.header() - if hdr is not None: - cap = hdr['capacity'] - else: - cap = 0 - return '%s of length %s, capacity %s' % (type, self.val['size'], cap) - - def children(self): - hdr = self.header() - if hdr is None: - return - is_map = self.display_hint() == 'map' - for i in range(hdr['capacity']): - metadata = self.val['metadata'] + i - if metadata.dereference()['used'] == 1: - yield ('[%d]' % i, (hdr['keys'] + i).dereference()) - if is_map: - yield ('[%d]' % i, (hdr['values'] + i).dereference()) - - def display_hint(self): - for field in self.header_ptr_type().target().fields(): - if field.name == 'values': - return 'map' - return 'array' - -# Handles both ArrayHashMap and ArrayHashMapUnmanaged. -class ArrayHashMapPrinter: - def __init__(self, val): - self.type = val.type - is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name) - self.val = val['unmanaged'] if is_managed else val - - def to_string(self): - type = self.type.name[len('std.array_hash_map.'):] - type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type) - return '%s of length %s' % (type, self.val['entries']['len']) - - def children(self): - entries = MultiArrayListPrinter(self.val['entries']) - len = self.val['entries']['len'] - fields = {} - for name, ptr in entries.slice(): - fields[str(name)] = ptr - - for i in range(len): - if 'key' in fields: - yield ('[%d]' % i, fields['key'][i]) - else: - yield ('[%d]' % i, '{}') - if 'value' in fields: - yield ('[%d]' % i, fields['value'][i]) - - def display_hint(self): - for name, ptr in MultiArrayListPrinter(self.val['entries']).slice(): - if name == 'value': - return 'map' - return 'array' - -class TypePrinter: - no_payload_count = 4096 - - # Keep in sync with src/type.zig - # Types which have no payload do not need to be entered here. - payload_type_names = { - 'array_u8': 'type.Len', - 'array_u8_sentinel_0': 'Len', - - 'single_const_pointer': 'ElemType', - 'single_mut_pointer': 'ElemType', - 'many_const_pointer': 'ElemType', - 'many_mut_pointer': 'ElemType', - 'c_const_pointer': 'ElemType', - 'c_mut_pointer': 'ElemType', - 'const_slice': 'ElemType', - 'mut_slice': 'ElemType', - 'optional': 'ElemType', - 'optional_single_mut_pointer': 'ElemType', - 'optional_single_const_pointer': 'ElemType', - 'anyframe_T': 'ElemType', - - 'int_signed': 'Bits', - 'int_unsigned': 'Bits', - - 'error_set': 'ErrorSet', - 'error_set_inferred': 'ErrorSetInferred', - 'error_set_merged': 'ErrorSetMerged', - - 'array': 'Array', - 'vector': 'Array', - - 'array_sentinel': 'ArraySentinel', - 'pointer': 'Pointer', - 'function': 'Function', - 'error_union': 'ErrorUnion', - 'error_set_single': 'Name', - 'opaque': 'Opaque', - 'struct': 'Struct', - 'union': 'Union', - 'union_tagged': 'Union', - 'enum_full, .enum_nonexhaustive': 'EnumFull', - 'enum_simple': 'EnumSimple', - 'enum_numbered': 'EnumNumbered', - 'empty_struct': 'ContainerScope', - 'tuple': 'Tuple', - 'anon_struct': 'AnonStruct', - } - - def __init__(self, val): - self.val = val - - def tag(self): - tag_if_small_enough = self.val['tag_if_small_enough'] - tag_type = tag_if_small_enough.type - - if tag_if_small_enough < TypePrinter.no_payload_count: - return tag_if_small_enough - else: - return self.val['ptr_otherwise'].dereference()['tag'] - - def payload_type(self): - tag = self.tag() - if tag is None: - return None - - type_name = TypePrinter.payload_type_names.get(str(tag)) - if type_name is None: - return None - return gdb.lookup_type('struct type.%s' % type_name) - - def to_string(self): - tag = self.tag() - if tag is None: - return '(invalid type)' - if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count: - return '.%s' % str(tag) - return None - - def children(self): - if self.val['tag_if_small_enough'] < TypePrinter.no_payload_count: - return - - yield ('tag', '.%s' % str(self.tag())) - - payload_type = self.payload_type() - if payload_type is not None: - yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) - -class ValuePrinter: - no_payload_count = 4096 - - # Keep in sync with src/value.zig - # Values which have no payload do not need to be entered here. - payload_type_names = { - 'big_int_positive': 'BigInt', - 'big_int_negative': 'BigInt', - - 'extern_fn': 'ExternFn', - - 'decl_ref': 'Decl', - - 'repeated': 'SubValue', - 'eu_payload': 'SubValue', - 'opt_payload': 'SubValue', - 'empty_array_sentinel': 'SubValue', - - 'eu_payload_ptr': 'PayloadPtr', - 'opt_payload_ptr': 'PayloadPtr', - - 'bytes': 'Bytes', - 'enum_literal': 'Bytes', - - 'slice': 'Slice', - - 'enum_field_index': 'U32', - - 'ty': 'Ty', - 'int_type': 'IntType', - 'int_u64': 'U64', - 'int_i64': 'I64', - 'function': 'Function', - 'variable': 'Variable', - 'decl_ref_mut': 'DeclRefMut', - 'elem_ptr': 'ElemPtr', - 'field_ptr': 'FieldPtr', - 'float_16': 'Float_16', - 'float_32': 'Float_32', - 'float_64': 'Float_64', - 'float_80': 'Float_80', - 'float_128': 'Float_128', - 'error': 'Error', - 'inferred_alloc': 'InferredAlloc', - 'inferred_alloc_comptime': 'InferredAllocComptime', - 'aggregate': 'Aggregate', - 'union': 'Union', - 'bound_fn': 'BoundFn', - } - - def __init__(self, val): - self.val = val - - def tag(self): - tag_if_small_enough = self.val['tag_if_small_enough'] - tag_type = tag_if_small_enough.type - - if tag_if_small_enough < ValuePrinter.no_payload_count: - return tag_if_small_enough - else: - return self.val['ptr_otherwise'].dereference()['tag'] - - def payload_type(self): - tag = self.tag() - if tag is None: - return None - - type_name = ValuePrinter.payload_type_names.get(str(tag)) - if type_name is None: - return None - return gdb.lookup_type('struct value.%s' % type_name) - - def to_string(self): - tag = self.tag() - if tag is None: - return '(invalid value)' - if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: - return '.%s' % str(tag) - return None - - def children(self): - if self.val['tag_if_small_enough'] < ValuePrinter.no_payload_count: - return - - yield ('tag', '.%s' % str(self.tag())) - - payload_type = self.payload_type() - if payload_type is not None: - yield ('payload', self.val['ptr_otherwise'].cast(payload_type.pointer()).dereference()['data']) - -pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler') -pp1.add_printer('Buf', '^Buf$', BufPrinter) -pp1.add_printer('ZigList', '^ZigList$', BufPrinter) -pp1.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter) -gdb.printing.register_pretty_printer(gdb.current_objfile(), pp1) - -pplang = gdb.printing.RegexpCollectionPrettyPrinter('Zig language') -pplang.add_printer('Slice', '^\[\]u8', SliceStringPrinter) -pplang.add_printer('Slice', '^\[\]', SlicePrinter) -gdb.printing.register_pretty_printer(gdb.current_objfile(), pplang) - -ppstd = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library') -ppstd.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter) -ppstd.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter) -ppstd.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter) -ppstd.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter) -gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd) - -pp2 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage2 compiler') -pp2.add_printer('Type', r'^type\.Type$', TypePrinter) -pp2.add_printer('Value', r'^value\.Value$', ValuePrinter) -gdb.printing.register_pretty_printer(gdb.current_objfile(), pp2) - diff --git a/tools/zig_gdb_pretty_printers.py b/tools/zig_gdb_pretty_printers.py index 3f8c31796a..7397097cc1 100644 --- a/tools/zig_gdb_pretty_printers.py +++ b/tools/zig_gdb_pretty_printers.py @@ -1,5 +1,5 @@ -# gdb pretty printers for Zig language constructs - +# pretty printing for the language. +# put "source /path/to/zig_gdb_pretty_printers.py" in ~/.gdbinit to load it automatically. import gdb.printing class ZigPrettyPrinter(gdb.printing.PrettyPrinter):