authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-02 19:04:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-03 12:43:12-05:00
log2834b937f143aa80e3730706dac5ff44cea3a67d
tree7c30f364da78b2738adbfb4cb392e2228dd1553d
parent6be5946ed8026f2a7ae990aced9572f229acecf4

link: give executable bit to wasm executables sometimes

Give +x to the .wasm file if it is an executable and the OS is WASI. Some systems may be configured to execute such binaries directly. Even if that is not the case, it means we will get "exec format error" when trying to run it rather than "access denied", and then can react to that in the same way as trying to run an ELF file from a foreign CPU architecture. This is part of the strategy to unify RunStep and EmulatableRunStep.

1 files changed, 27 insertions(+), 5 deletions(-)

src/link/Wasm.zig+27-5
...@@ -345,7 +345,17 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -345,7 +345,17 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
345 }345 }
346346
347 // TODO: read the file and keep valid parts instead of truncating347 // TODO: read the file and keep valid parts instead of truncating
348 const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true });348 const file = try options.emit.?.directory.handle.createFile(sub_path, .{
349 .truncate = true,
350 .read = true,
351 .mode = if (fs.has_executable_bit)
352 if (options.target.os.tag == .wasi and options.output_mode == .Exe)
353 fs.File.default_mode | 0b001_000_000
354 else
355 fs.File.default_mode
356 else
357 0,
358 });
349 wasm_bin.base.file = file;359 wasm_bin.base.file = file;
350 wasm_bin.name = sub_path;360 wasm_bin.name = sub_path;
351361
...@@ -3750,10 +3760,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3750,10 +3760,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3750 if (wasm.base.options.import_symbols) {3760 if (wasm.base.options.import_symbols) {
3751 try argv.append("--allow-undefined");3761 try argv.append("--allow-undefined");
3752 }3762 }
3753 try argv.appendSlice(&[_][]const u8{3763 try argv.appendSlice(&.{ "-o", full_out_path });
3754 "-o",
3755 full_out_path,
3756 });
37573764
3758 if (target.cpu.arch == .wasm64) {3765 if (target.cpu.arch == .wasm64) {
3759 try argv.append("-mwasm64");3766 try argv.append("-mwasm64");
...@@ -3889,6 +3896,21 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3889,6 +3896,21 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3889 }3896 }
3890 }3897 }
3891 }3898 }
3899
3900 // Give +x to the .wasm file if it is an executable and the OS is WASI.
3901 // Some systems may be configured to execute such binaries directly. Even if that
3902 // is not the case, it means we will get "exec format error" when trying to run
3903 // it, and then can react to that in the same way as trying to run an ELF file
3904 // from a foreign CPU architecture.
3905 if (fs.has_executable_bit and target.os.tag == .wasi and
3906 wasm.base.options.output_mode == .Exe)
3907 {
3908 // TODO: what's our strategy for reporting linker errors from this function?
3909 // report a nice error here with the file path if it fails instead of
3910 // just returning the error code.
3911 // chmod does not interact with umask, so we use a conservative -rwxr--r-- here.
3912 try std.os.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0);
3913 }
3892 }3914 }
38933915
3894 if (!wasm.base.options.disable_lld_caching) {3916 if (!wasm.base.options.disable_lld_caching) {