authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-03-16 15:38:30+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-03-16 15:50:03+01:00
logfeb8981a95988434506bad9864498e2ff1ff9243
treea22230a1a1c91ac5c6101bd89e9ab2e30a01a327
parente18c29af5bf873ed3165ab9abb57b2246f37c406

gdb: add slice, multi array list, and array hash map printers


3 files changed, 155 insertions(+), 15 deletions(-)

lib/std/hash_map.zig+14
......@@ -1,4 +1,5 @@
11const std = @import("std.zig");
2const builtin = @import("builtin");
23const assert = debug.assert;
34const autoHash = std.hash.autoHash;
45const debug = std.debug;
......@@ -1576,6 +1577,19 @@ pub fn HashMapUnmanaged(
15761577 self.metadata = null;
15771578 self.available = 0;
15781579 }
1580
1581 /// This function is used in tools/zig-gdb.py to fetch the header type to facilitate
1582 /// fancy debug printing for this type.
1583 fn gdbHelper(self: *Self, hdr: *Header) void {
1584 _ = self;
1585 _ = hdr;
1586 }
1587
1588 comptime {
1589 if (builtin.mode == .Debug) {
1590 _ = gdbHelper;
1591 }
1592 }
15791593 };
15801594}
15811595
lib/std/multi_array_list.zig+14
......@@ -1,4 +1,5 @@
11const std = @import("std.zig");
2const builtin = @import("builtin");
23const assert = std.debug.assert;
34const meta = std.meta;
45const mem = std.mem;
......@@ -433,6 +434,19 @@ pub fn MultiArrayList(comptime S: type) type {
433434 fn FieldType(field: Field) type {
434435 return meta.fieldInfo(S, field).field_type;
435436 }
437
438 /// This function is used in tools/zig-gdb.py to fetch the child type to facilitate
439 /// fancy debug printing for this type.
440 fn gdbHelper(self: *Self, child: *S) void {
441 _ = self;
442 _ = child;
443 }
444
445 comptime {
446 if (builtin.mode == .Debug) {
447 _ = gdbHelper;
448 }
449 }
436450 };
437451}
438452
tools/zig-gdb.py+127-15
......@@ -32,6 +32,27 @@ class BufPrinter:
3232 def display_hint(self):
3333 return 'string'
3434
35class SlicePrinter:
36 def __init__(self, val):
37 self.val = val
38
39 def children(self):
40 for i in range(self.val['len']):
41 yield ('[%d]' % i, (self.val['ptr'] + i).dereference())
42
43 def display_hint(self):
44 return 'array'
45
46class SliceStringPrinter:
47 def __init__(self, val):
48 self.val = val
49
50 def to_string(self):
51 return self.val['ptr'].string(length=self.val['len'])
52
53 def display_hint(self):
54 return 'string'
55
3556# Handles both ArrayList and ArrayListUnmanaged.
3657class ArrayListPrinter:
3758 def __init__(self, val):
......@@ -39,52 +60,143 @@ class ArrayListPrinter:
3960
4061 def to_string(self):
4162 type = self.val.type.name[len('std.array_list.'):]
42 type = re.sub(r'ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
63 type = re.sub(r'^ArrayListAligned(Unmanaged)?\((.*),null\)$', r'ArrayList\1(\2)', type)
4364 return '%s of length %s, capacity %s' % (type, self.val['items']['len'], self.val['capacity'])
4465
4566 def children(self):
46 for i in range(int(self.val['items']['len'])):
67 for i in range(self.val['items']['len']):
4768 item = self.val['items']['ptr'] + i
4869 yield ('[%d]' % i, item.dereference())
4970
5071 def display_hint(self):
5172 return 'array'
5273
53# Handles both HashMap and HashMapUnmanaged
74class MultiArrayListPrinter:
75 def __init__(self, val):
76 self.val = val
77
78 def child_type(self):
79 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
80 return helper_fn.type.fields()[1].type.target()
81
82 def to_string(self):
83 type = self.val.type.name[len('std.multi_array_list.'):]
84 return '%s of length %s, capacity %s' % (type, self.val['len'], self.val['capacity'])
85
86 def slice(self):
87 fields = self.child_type().fields()
88 base = self.val['bytes']
89 cap = self.val['capacity']
90 len = self.val['len']
91
92 if len == 0:
93 return
94
95 fields = sorted(fields, key=lambda field: field.type.alignof, reverse=True)
96
97 for field in fields:
98 ptr = base.cast(field.type.pointer()).dereference().cast(field.type.array(len - 1))
99 base += field.type.sizeof * cap
100 yield (field.name, ptr)
101
102 def children(self):
103 for i, (name, ptr) in enumerate(self.slice()):
104 yield ('[%d]' % i, name)
105 yield ('[%d]' % i, ptr)
106
107 def display_hint(self):
108 return 'map'
109
110# Handles both HashMap and HashMapUnmanaged.
54111class HashMapPrinter:
55112 def __init__(self, val):
56113 self.type = val.type
57114 is_managed = re.search(r'^std\.hash_map\.HashMap\(', self.type.name)
58115 self.val = val['unmanaged'] if is_managed else val
59116
117 def header_ptr_type(self):
118 (helper_fn, _) = gdb.lookup_symbol('%s.gdbHelper' % self.val.type.name)
119 return helper_fn.type.fields()[1].type
120
60121 def header(self):
61 (header_fn, _) = gdb.lookup_symbol('%s.header' % self.val.type.name)
62 header_ptr_type = header_fn.type.target()
63 return (self.val['metadata'].cast(header_ptr_type) - 1).dereference()
122 if self.val['metadata'] == 0:
123 return None
124 return (self.val['metadata'].cast(self.header_ptr_type()) - 1).dereference()
64125
65126 def to_string(self):
66127 type = self.type.name[len('std.hash_map.'):]
67128 type = re.sub(r'^HashMap(Unmanaged)?\((.*),std.hash_map.AutoContext\(.*$', r'AutoHashMap\1(\2)', type)
68 return '%s of length %s, capacity %s' % (type, self.val['size'], self.header()['capacity'])
129 hdr = self.header()
130 if hdr is not None:
131 cap = hdr['capacity']
132 else:
133 cap = 0
134 return '%s of length %s, capacity %s' % (type, self.val['size'], cap)
69135
70136 def children(self):
71137 hdr = self.header()
72 for i in range(int(hdr['capacity'])):
138 if hdr is None:
139 return
140 is_map = self.display_hint() == 'map'
141 for i in range(hdr['capacity']):
73142 metadata = self.val['metadata'] + i
74143 if metadata.dereference()['used'] == 1:
75144 yield ('[%d]' % i, (hdr['keys'] + i).dereference())
76 yield ('[%d]' % i, (hdr['values'] + i).dereference())
145 if is_map:
146 yield ('[%d]' % i, (hdr['values'] + i).dereference())
77147
78148 def display_hint(self):
79 return 'map'
149 for field in self.header_ptr_type().target().fields():
150 if field.name == 'values':
151 return 'map'
152 return 'array'
153
154# Handles both ArrayHashMap and ArrayHashMapUnmanaged.
155class ArrayHashMapPrinter:
156 def __init__(self, val):
157 self.type = val.type
158 is_managed = re.search(r'^std\.array_hash_map\.ArrayHashMap\(', self.type.name)
159 self.val = val['unmanaged'] if is_managed else val
160
161 def to_string(self):
162 type = self.type.name[len('std.array_hash_map.'):]
163 type = re.sub(r'^ArrayHashMap(Unmanaged)?\((.*),std.array_hash_map.AutoContext\(.*$', r'AutoArrayHashMap\1(\2)', type)
164 return '%s of length %s' % (type, self.val['entries']['len'])
165
166 def children(self):
167 entries = MultiArrayListPrinter(self.val['entries'])
168 len = self.val['entries']['len']
169 fields = {}
170 for name, ptr in entries.slice():
171 fields[str(name)] = ptr
172
173 for i in range(len):
174 if 'key' in fields:
175 yield ('[%d]' % i, fields['key'][i])
176 else:
177 yield ('[%d]' % i, '{}')
178 if 'value' in fields:
179 yield ('[%d]' % i, fields['value'][i])
180
181 def display_hint(self):
182 for name, ptr in MultiArrayListPrinter(self.val['entries']).slice():
183 if name == 'value':
184 return 'map'
185 return 'array'
186
187pp1 = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
188pp1.add_printer('Buf', '^Buf$', BufPrinter)
189pp1.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
190pp1.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
191gdb.printing.register_pretty_printer(gdb.current_objfile(), pp1)
80192
81pp = gdb.printing.RegexpCollectionPrettyPrinter('Zig stage1 compiler')
82pp.add_printer('Buf', '^Buf$', BufPrinter)
83pp.add_printer('ZigList<char>', '^ZigList<char>$', BufPrinter)
84pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter)
85gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
193pplang = gdb.printing.RegexpCollectionPrettyPrinter('Zig language')
194pplang.add_printer('Slice', '^\[\]u8', SliceStringPrinter)
195pplang.add_printer('Slice', '^\[\]', SlicePrinter)
86196
87197ppstd = gdb.printing.RegexpCollectionPrettyPrinter('Zig standard library')
88198ppstd.add_printer('ArrayList', r'^std\.array_list\.ArrayListAligned(Unmanaged)?\(.*\)$', ArrayListPrinter)
199ppstd.add_printer('MultiArrayList', r'^std\.multi_array_list\.MultiArrayList\(.*\)$', MultiArrayListPrinter)
89200ppstd.add_printer('HashMap', r'^std\.hash_map\.HashMap(Unmanaged)?\(.*\)$', HashMapPrinter)
201ppstd.add_printer('ArrayHashMap', r'^std\.array_hash_map\.ArrayHashMap(Unmanaged)?\(.*\)$', ArrayHashMapPrinter)
90202gdb.printing.register_pretty_printer(gdb.current_objfile(), ppstd)