diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-27 21:49:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-27 21:49:06 +0100 |
| commit | 3bc1c719bd632e6baccb574bf75cb93f0bdef08f (patch) | |
| tree | 288fea5f073ec13c4b435a853e40f7c1d1e90ab4 /src/link.zig | |
| parent | daf6c0da5b2d96530dea2d2a907f2b2ba55c8ba6 (diff) | |
| parent | 5ed76268c9f0ecca8c5d62cb7e56da05aa8f1f7c (diff) | |
| download | zig-3bc1c719bd632e6baccb574bf75cb93f0bdef08f.tar.gz zig-3bc1c719bd632e6baccb574bf75cb93f0bdef08f.zip | |
Merge pull request #7231 from kubkon/stage2-arm-macos
stage2: Hello, Silicon!\n
Diffstat (limited to 'src/link.zig')
| -rw-r--r-- | src/link.zig | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/link.zig b/src/link.zig index 064c178d66..e8a9f3d730 100644 --- a/src/link.zig +++ b/src/link.zig @@ -238,7 +238,29 @@ pub const File = struct { pub fn makeExecutable(base: *File) !void { switch (base.tag) { - .coff, .elf, .macho => if (base.file) |f| { + .macho => if (base.file) |f| { + if (base.intermediary_basename != null) { + // The file we have open is not the final file that we want to + // make executable, so we don't have to close it. + return; + } + if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) { + if (base.options.target.cpu.arch != .aarch64) return; // If we're not targeting aarch64, nothing to do. + // XNU starting with Big Sur running on arm64 is caching inodes of running binaries. + // Any change to the binary will effectively invalidate the kernel's cache + // resulting in a SIGKILL on each subsequent run. Since when doing incremental + // linking we're modifying a binary in-place, this will end up with the kernel + // killing it on every subsequent run. To circumvent it, we will copy the file + // into a new inode, remove the original file, and rename the copy to match + // the original file. This is super messy, but there doesn't seem any other + // way to please the XNU. + const emit = base.options.emit orelse return; + try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{}); + } + f.close(); + base.file = null; + }, + .coff, .elf => if (base.file) |f| { if (base.intermediary_basename != null) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. |
