authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 00:36:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 20:33:47+02:00
logb13b36a71d63b6dfe4beda940fa6f9488fb3690a
treed050a766f8105c2cbfdec75b4821fea30dbbbaa2
parente76fb8d8c82ffc9fdeef2de0a6008c756103811b
signaturelock-open Commit is signed but in an unrecognized format.

Approach using array list for auto mem mgmt

Signed-off-by: Jakub Konka <kubkon@jakubkonka.com>

1 files changed, 46 insertions(+), 35 deletions(-)

src/link/MachO.zig+46-35
......@@ -151,37 +151,49 @@ const Trie = struct {
151151 return node;
152152 }
153153
154 pub fn write(self: Node, buf: []u8, offset: u64) error{NoSpaceLeft}!usize {
155 var pos: usize = 0;
154 pub fn write(self: Node, alloc: *Allocator, buffer: *std.ArrayListUnmanaged(u8)) Trie.WriteError!void {
156155 if (self.offset) |off| {
157 var info_buf_pos: usize = 0;
156 // Terminal node info: encode export flags and vmaddr offset of this symbol.
157 var info_buf_len: usize = 0;
158158 var info_buf: [@sizeOf(u64) * 2]u8 = undefined;
159 info_buf_pos += try std.debug.leb.writeULEB128Mem(info_buf[0..], self.export_flags.?);
160 info_buf_pos += try std.debug.leb.writeULEB128Mem(info_buf[info_buf_pos..], off);
161 log.debug("info_buf = {x}\n", .{info_buf[0..info_buf_pos]});
162 pos += try std.debug.leb.writeULEB128Mem(buf[pos..], info_buf_pos);
163 mem.copy(u8, buf[pos..], info_buf[0..info_buf_pos]);
164 pos += info_buf_pos;
165 log.debug("buf = {x}\n", .{buf});
159 info_buf_len += try std.debug.leb.writeULEB128Mem(info_buf[0..], self.export_flags.?);
160 info_buf_len += try std.debug.leb.writeULEB128Mem(info_buf[info_buf_len..], off);
161
162 // Encode the size of the terminal node info.
163 var size_buf: [@sizeOf(u64)]u8 = undefined;
164 const size_buf_len = try std.debug.leb.writeULEB128Mem(size_buf[0..], info_buf_len);
165
166 // Now, write them to the output buffer.
167 try buffer.ensureCapacity(alloc, buffer.items.len + info_buf_len + size_buf_len);
168 buffer.appendSliceAssumeCapacity(size_buf[0..size_buf_len]);
169 buffer.appendSliceAssumeCapacity(info_buf[0..info_buf_len]);
166170 } else {
167 buf[pos] = 0;
168 pos += 1;
171 // Non-terminal node is delimited by 0 byte.
172 try buffer.append(alloc, 0);
169173 }
170 buf[pos] = @intCast(u8, self.edges.items.len);
171 pos += 1;
172
173 for (self.edges.items) |edge| {
174 mem.copy(u8, buf[pos..], edge.label);
175 pos += edge.label.len;
176 buf[pos] = 0;
177 pos += 1;
178 const curr_offset = pos + offset + 1;
179 pos += try std.debug.leb.writeULEB128Mem(buf[pos..], curr_offset);
180 pos += try edge.to.write(buf[pos..], curr_offset);
181 log.debug("buf = {x}\n", .{buf});
174 // Write number of edges (max legal number of edges is 256).
175 try buffer.append(alloc, @intCast(u8, self.edges.items.len));
176
177 var node_offset_info: [@sizeOf(u8)]u64 = undefined;
178 for (self.edges.items) |edge, i| {
179 // Write edges labels leaving out space in-between to later populate
180 // with offsets to each node.
181 try buffer.ensureCapacity(alloc, buffer.items.len + edge.label.len + 1 + @sizeOf(u64)); // +1 to account for null-byte
182 buffer.appendSliceAssumeCapacity(edge.label);
183 buffer.appendAssumeCapacity(0);
184 node_offset_info[i] = buffer.items.len;
185 const padding = [_]u8{0} ** @sizeOf(u64);
186 buffer.appendSliceAssumeCapacity(padding[0..]);
182187 }
183188
184 return pos;
189 for (self.edges.items) |edge, i| {
190 const offset = buffer.items.len;
191 try edge.to.write(alloc, buffer);
192 // We can now populate the offset to the node pointed by this edge.
193 var offset_buf: [@sizeOf(u64)]u8 = undefined;
194 const offset_buf_len = try std.debug.leb.writeULEB128Mem(offset_buf[0..], offset);
195 mem.copy(u8, buffer.items[node_offset_info[i]..], offset_buf[0..offset_buf_len]);
196 }
185197 }
186198 };
187199
......@@ -191,16 +203,10 @@ const Trie = struct {
191203 return self.root.put(alloc, null, 0, word);
192204 }
193205
194 pub fn write(self: Trie, alloc: *Allocator, file: *fs.File, offset: u64) !void {
195 // TODO get the actual node count
196 const count = 10;
197 const node_size = @sizeOf(u64) * 2;
206 pub const WriteError = error{ OutOfMemory, NoSpaceLeft };
198207
199 var buf = try alloc.alloc(u8, count * node_size);
200 defer alloc.free(buf);
201
202 const written = try self.root.write(buf, 0);
203 return file.pwriteAll(buf[0..written], offset);
208 pub fn write(self: Trie, alloc: *Allocator, buffer: *std.ArrayListUnmanaged(u8)) WriteError!void {
209 return self.root.write(alloc, buffer);
204210 }
205211
206212 pub fn deinit(self: *Trie, alloc: *Allocator) void {
......@@ -1544,8 +1550,13 @@ fn writeExportTrie(self: *MachO) !void {
15441550 node.export_flags = 0; // TODO workout creation of export flags
15451551 }
15461552
1553 var buffer: std.ArrayListUnmanaged(u8) = .{};
1554 defer buffer.deinit(self.base.allocator);
1555
1556 try trie.write(self.base.allocator, &buffer);
1557
15471558 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo;
1548 try trie.write(self.base.allocator, &self.base.file.?, dyld_info.export_off);
1559 try self.base.file.?.pwriteAll(buffer.items, dyld_info.export_off);
15491560}
15501561
15511562fn writeStringTable(self: *MachO) !void {