authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-13 14:15:23+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-13 14:15:26+01:00
log68c224d6ec9e710e70b4500c5b73fb40780621c0
tree4ea7a09df879feaeb781d391b354ee355d88bcc5
parent633c4a2a6094cd301648c2e2c6b5002917e0ef2c

macho: simplify writing atoms for stage2

Also, fix premature exit in `link.File.makeWritable` in case we are running M1 but executing binaries using Rosetta2.

2 files changed, 16 insertions(+), 54 deletions(-)

src/link.zig+12-11
...@@ -373,17 +373,18 @@ pub const File = struct {...@@ -373,17 +373,18 @@ pub const File = struct {
373 return;373 return;
374 }374 }
375 if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {375 if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {
376 if (base.options.target.cpu.arch != .aarch64) return; // If we're not targeting aarch64, nothing to do.376 if (base.options.target.cpu.arch == .aarch64) {
377 // XNU starting with Big Sur running on arm64 is caching inodes of running binaries.377 // XNU starting with Big Sur running on arm64 is caching inodes of running binaries.
378 // Any change to the binary will effectively invalidate the kernel's cache378 // Any change to the binary will effectively invalidate the kernel's cache
379 // resulting in a SIGKILL on each subsequent run. Since when doing incremental379 // resulting in a SIGKILL on each subsequent run. Since when doing incremental
380 // linking we're modifying a binary in-place, this will end up with the kernel380 // linking we're modifying a binary in-place, this will end up with the kernel
381 // killing it on every subsequent run. To circumvent it, we will copy the file381 // killing it on every subsequent run. To circumvent it, we will copy the file
382 // into a new inode, remove the original file, and rename the copy to match382 // into a new inode, remove the original file, and rename the copy to match
383 // the original file. This is super messy, but there doesn't seem any other383 // the original file. This is super messy, but there doesn't seem any other
384 // way to please the XNU.384 // way to please the XNU.
385 const emit = base.options.emit orelse return;385 const emit = base.options.emit orelse return;
386 try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{});386 try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{});
387 }
387 }388 }
388 f.close();389 f.close();
389 base.file = null;390 base.file = null;
src/link/MachO.zig+4-43
...@@ -2189,10 +2189,6 @@ fn writePadding(self: *MachO, match: MatchingSection, size: usize, writer: anyty...@@ -2189,10 +2189,6 @@ fn writePadding(self: *MachO, match: MatchingSection, size: usize, writer: anyty
2189}2189}
21902190
2191fn writeAtoms(self: *MachO) !void {2191fn writeAtoms(self: *MachO) !void {
2192 var buffer = std.ArrayList(u8).init(self.base.allocator);
2193 defer buffer.deinit();
2194 var file_offset: ?u64 = null;
2195
2196 var it = self.atoms.iterator();2192 var it = self.atoms.iterator();
2197 while (it.next()) |entry| {2193 while (it.next()) |entry| {
2198 const match = entry.key_ptr.*;2194 const match = entry.key_ptr.*;
...@@ -2205,50 +2201,15 @@ fn writeAtoms(self: *MachO) !void {...@@ -2205,50 +2201,15 @@ fn writeAtoms(self: *MachO) !void {
22052201
2206 log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() });2202 log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() });
22072203
2208 while (atom.prev) |prev| {
2209 atom = prev;
2210 }
2211
2212 while (true) {2204 while (true) {
2213 if (atom.dirty or self.invalidate_relocs) {2205 if (atom.dirty or self.invalidate_relocs) {
2214 const atom_sym = self.locals.items[atom.local_sym_index];2206 try self.writeAtom(atom, match);
2215 const padding_size: usize = if (atom.next) |next| blk: {
2216 const next_sym = self.locals.items[next.local_sym_index];
2217 const size = next_sym.n_value - (atom_sym.n_value + atom.size);
2218 break :blk try math.cast(usize, size);
2219 } else 0;
2220
2221 log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym });
2222
2223 try atom.resolveRelocs(self);
2224 try buffer.appendSlice(atom.code.items);
2225 try buffer.ensureUnusedCapacity(padding_size);
2226 try self.writePadding(match, padding_size, buffer.writer());
2227
2228 if (file_offset == null) {
2229 file_offset = sect.offset + atom_sym.n_value - sect.addr;
2230 }
2231 atom.dirty = false;2207 atom.dirty = false;
2232 } else {
2233 if (file_offset) |off| {
2234 log.debug(" (writing at file offset 0x{x})", .{off});
2235 try self.base.file.?.pwriteAll(buffer.items, off);
2236 }
2237 file_offset = null;
2238 buffer.clearRetainingCapacity();
2239 }2208 }
22402209
2241 if (atom.next) |next| {2210 if (atom.prev) |prev| {
2242 atom = next;2211 atom = prev;
2243 } else {2212 } else break;
2244 if (file_offset) |off| {
2245 log.debug(" (writing at file offset 0x{x})", .{off});
2246 try self.base.file.?.pwriteAll(buffer.items, off);
2247 }
2248 file_offset = null;
2249 buffer.clearRetainingCapacity();
2250 break;
2251 }
2252 }2213 }
2253 }2214 }
2254}2215}