| author | |
| committer | |
| log | 68c224d6ec9e710e70b4500c5b73fb40780621c0 |
| tree | 4ea7a09df879feaeb781d391b354ee355d88bcc5 |
| parent | 633c4a2a6094cd301648c2e2c6b5002917e0ef2c |
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 | 373 | return; |
| 374 | 374 | } |
| 375 | 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. | |
| 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 cache | |
| 379 | // 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 kernel | |
| 381 | // 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 match | |
| 383 | // the original file. This is super messy, but there doesn't seem any other | |
| 384 | // way to please the XNU. | |
| 385 | const emit = base.options.emit orelse return; | |
| 386 | try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{}); | |
| 376 | if (base.options.target.cpu.arch == .aarch64) { | |
| 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 cache | |
| 379 | // 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 kernel | |
| 381 | // 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 match | |
| 383 | // the original file. This is super messy, but there doesn't seem any other | |
| 384 | // way to please the XNU. | |
| 385 | const emit = base.options.emit orelse return; | |
| 386 | try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{}); | |
| 387 | } | |
| 387 | 388 | } |
| 388 | 389 | f.close(); |
| 389 | 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 | 2189 | } |
| 2190 | 2190 | |
| 2191 | 2191 | fn 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 | 2192 | var it = self.atoms.iterator(); |
| 2197 | 2193 | while (it.next()) |entry| { |
| 2198 | 2194 | const match = entry.key_ptr.*; |
| ... | ... | @@ -2205,50 +2201,15 @@ fn writeAtoms(self: *MachO) !void { |
| 2205 | 2201 | |
| 2206 | 2202 | log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() }); |
| 2207 | 2203 | |
| 2208 | while (atom.prev) |prev| { | |
| 2209 | atom = prev; | |
| 2210 | } | |
| 2211 | ||
| 2212 | 2204 | while (true) { |
| 2213 | 2205 | if (atom.dirty or self.invalidate_relocs) { |
| 2214 | const atom_sym = self.locals.items[atom.local_sym_index]; | |
| 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 | } | |
| 2206 | try self.writeAtom(atom, match); | |
| 2231 | 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 | } |
| 2240 | 2209 | |
| 2241 | if (atom.next) |next| { | |
| 2242 | atom = next; | |
| 2243 | } else { | |
| 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 | } | |
| 2210 | if (atom.prev) |prev| { | |
| 2211 | atom = prev; | |
| 2212 | } else break; | |
| 2252 | 2213 | } |
| 2253 | 2214 | } |
| 2254 | 2215 | } |