diff options
| author | Robin Voetter <robin@voetter.nl> | 2022-03-16 15:38:30 +0100 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2022-03-16 15:50:03 +0100 |
| commit | feb8981a95988434506bad9864498e2ff1ff9243 (patch) | |
| tree | a22230a1a1c91ac5c6101bd89e9ab2e30a01a327 /tools | |
| parent | e18c29af5bf873ed3165ab9abb57b2246f37c406 (diff) | |
| download | zig-feb8981a95988434506bad9864498e2ff1ff9243.tar.gz zig-feb8981a95988434506bad9864498e2ff1ff9243.zip | |
gdb: add slice, multi array list, and array hash map printers
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/zig-gdb.py | 142 |
1 files changed, 127 insertions, 15 deletions
diff --git a/tools/zig-gdb.py b/tools/zig-gdb.py index 3a656d9b22..b6ba4a7baf 100644 --- a/tools/zig-gdb.py +++ b/tools/zig-gdb.py @@ -32,6 +32,27 @@ class BufPrinter: 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): @@ -39,52 +60,143 @@ class ArrayListPrinter: 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) + 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(int(self.val['items']['len'])): + 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' -# Handles both HashMap and HashMapUnmanaged +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): - (header_fn, _) = gdb.lookup_symbol('%s.header' % self.val.type.name) - header_ptr_type = header_fn.type.target() - return (self.val['metadata'].cast(header_ptr_type) - 1).dereference() + 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) - return '%s of length %s, capacity %s' % (type, self.val['size'], self.header()['capacity']) + 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() - for i in range(int(hdr['capacity'])): + 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()) - yield ('[%d]' % i, (hdr['values'] + i).dereference()) + if is_map: + yield ('[%d]' % i, (hdr['values'] + i).dereference()) def display_hint(self): - return 'map' + 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' + +pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler') +pp1.add_printer('Buf', '^Buf$', BufPrinter) +pp1.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter) +pp1.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter) +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp1) -pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler') -pp.add_printer('Buf', '^Buf$', BufPrinter) -pp.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter) -pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter) -gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) +pplang = gdb.printing.RegexpCollectionPrettyPrinter('Zig language') +pplang.add_printer('Slice', '^\[\]u8', SliceStringPrinter) +pplang.add_printer('Slice', '^\[\]', SlicePrinter) 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) |
