From 8e5f7f5fe89e1c2979df2c735046c81e37c3f842 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 10 Sep 2021 15:37:51 +0200 Subject: [PATCH] macho: write adjacent atoms to in-memory buffer and then commit the large buffer into file. --- src/link/MachO.zig | 48 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 2705d47a85..63e716907f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1766,20 +1766,60 @@ fn allocateGlobalSymbols(self: *MachO) !void { } fn writeAtoms(self: *MachO) !void { + var buffer = std.ArrayList(u8).init(self.base.allocator); + defer buffer.deinit(); + var file_offset: ?u64 = null; + var it = self.blocks.iterator(); while (it.next()) |entry| { const match = entry.key_ptr.*; + const seg = self.load_commands.items[match.seg].Segment; + const sect = seg.sections.items[match.sect]; var atom: *TextBlock = entry.value_ptr.*; + while (atom.prev) |prev| { + atom = prev; + } + while (true) { if (atom.dirty) { - try self.writeAtom(atom, match); + const atom_sym = self.locals.items[atom.local_sym_index]; + const padding_size: u64 = if (atom.next) |next| blk: { + const next_sym = self.locals.items[next.local_sym_index]; + break :blk next_sym.n_value - (atom_sym.n_value + atom.size); + } else 0; + + try atom.resolveRelocs(self); + try buffer.appendSlice(atom.code.items); + try buffer.ensureUnusedCapacity(padding_size); + + var i: usize = 0; + while (i < padding_size) : (i += 1) { + buffer.appendAssumeCapacity(0); + } + + if (file_offset == null) { + file_offset = sect.offset + atom_sym.n_value - sect.addr; + } atom.dirty = false; + } else { + if (file_offset) |off| { + try self.base.file.?.pwriteAll(buffer.items, off); + } + file_offset = null; + buffer.clearRetainingCapacity(); } - if (atom.prev) |prev| { - atom = prev; - } else break; + if (atom.next) |next| { + atom = next; + } else { + if (file_offset) |off| { + try self.base.file.?.pwriteAll(buffer.items, off); + } + file_offset = null; + buffer.clearRetainingCapacity(); + break; + } } } }