authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-12-25 22:04:01+01:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-12-25 22:32:21+01:00
log7802c26449657b205dcaa47bb6575bb26171c024
tree1f4ca594d37bf4d9c51d85ed63164b86c5771029
parent0c30e006c90db4e6ca77d9054d391340282b96f6

WebAssembly: do not link with --allow-undefined unconditionally

In #1622, when targeting WebAsembly, the --allow-undefined flag became unconditionally added to the linker. This is not always desirable. First, this is error prone. Code with references to unkown symbols will link just fine, but then fail at run-time. This behavior is inconsistent with all other targets. For freestanding wasm applications, and applications that only use WASI, undefined references are better reported at compile-time. This behavior is also inconsistent with clang itself. Autoconf and cmake scripts checking for function presence think that all tested functions exist, but then resulting application cannot run. For example, this is one of the reasons compilation of Ruby 3.2.0 to WASI fails with zig cc, while it works out of the box with clang. But all applications checking for symbol existence before compilation are affected. This reverts the behavior to the one Zig had before #1622, and introduces an `import_symbols` flag to ignore undefined symbols, assuming that the webassembly runtime will define them.

4 files changed, 13 insertions(+), 1 deletions(-)

src/Compilation.zig+2
...@@ -954,6 +954,7 @@ pub const InitOptions = struct {...@@ -954,6 +954,7 @@ pub const InitOptions = struct {
954 linker_allow_shlib_undefined: ?bool = null,954 linker_allow_shlib_undefined: ?bool = null,
955 linker_bind_global_refs_locally: ?bool = null,955 linker_bind_global_refs_locally: ?bool = null,
956 linker_import_memory: ?bool = null,956 linker_import_memory: ?bool = null,
957 linker_import_symbols: bool = false,
957 linker_import_table: bool = false,958 linker_import_table: bool = false,
958 linker_export_table: bool = false,959 linker_export_table: bool = false,
959 linker_initial_memory: ?u64 = null,960 linker_initial_memory: ?u64 = null,
...@@ -1811,6 +1812,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1811,6 +1812,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1811 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,1812 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1812 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,1813 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
1813 .import_memory = options.linker_import_memory orelse false,1814 .import_memory = options.linker_import_memory orelse false,
1815 .import_symbols = options.linker_import_symbols,
1814 .import_table = options.linker_import_table,1816 .import_table = options.linker_import_table,
1815 .export_table = options.linker_export_table,1817 .export_table = options.linker_export_table,
1816 .initial_memory = options.linker_initial_memory,1818 .initial_memory = options.linker_initial_memory,
src/link.zig+1
...@@ -128,6 +128,7 @@ pub const Options = struct {...@@ -128,6 +128,7 @@ pub const Options = struct {
128 compress_debug_sections: CompressDebugSections,128 compress_debug_sections: CompressDebugSections,
129 bind_global_refs_locally: bool,129 bind_global_refs_locally: bool,
130 import_memory: bool,130 import_memory: bool,
131 import_symbols: bool,
131 import_table: bool,132 import_table: bool,
132 export_table: bool,133 export_table: bool,
133 initial_memory: ?u64,134 initial_memory: ?u64,
src/link/Wasm.zig+3-1
...@@ -3461,8 +3461,10 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3461,8 +3461,10 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3461 } else if (wasm.base.options.entry == null) {3461 } else if (wasm.base.options.entry == null) {
3462 try argv.append("--no-entry"); // So lld doesn't look for _start.3462 try argv.append("--no-entry"); // So lld doesn't look for _start.
3463 }3463 }
3464 if (wasm.base.options.import_symbols) {
3465 try argv.appendSlice(&[_][]const u8{"--allow-undefined"});
3466 }
3464 try argv.appendSlice(&[_][]const u8{3467 try argv.appendSlice(&[_][]const u8{
3465 "--allow-undefined",
3466 "-o",3468 "-o",
3467 full_out_path,3469 full_out_path,
3468 });3470 });
src/main.zig+7
...@@ -517,6 +517,7 @@ const usage_build_generic =...@@ -517,6 +517,7 @@ const usage_build_generic =
517 \\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols517 \\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols
518 \\ -dead_strip_dylibs (Darwin) remove dylibs that are unreachable by the entry point or exported symbols518 \\ -dead_strip_dylibs (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
519 \\ --import-memory (WebAssembly) import memory from the environment519 \\ --import-memory (WebAssembly) import memory from the environment
520 \\ --import-symbols (WebAssembly) import missing symbols from the host environment
520 \\ --import-table (WebAssembly) import function table from the host environment521 \\ --import-table (WebAssembly) import function table from the host environment
521 \\ --export-table (WebAssembly) export function table to the host environment522 \\ --export-table (WebAssembly) export function table to the host environment
522 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory523 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory
...@@ -718,6 +719,7 @@ fn buildOutputType(...@@ -718,6 +719,7 @@ fn buildOutputType(
718 var linker_allow_shlib_undefined: ?bool = null;719 var linker_allow_shlib_undefined: ?bool = null;
719 var linker_bind_global_refs_locally: ?bool = null;720 var linker_bind_global_refs_locally: ?bool = null;
720 var linker_import_memory: ?bool = null;721 var linker_import_memory: ?bool = null;
722 var linker_import_symbols: bool = false;
721 var linker_import_table: bool = false;723 var linker_import_table: bool = false;
722 var linker_export_table: bool = false;724 var linker_export_table: bool = false;
723 var linker_initial_memory: ?u64 = null;725 var linker_initial_memory: ?u64 = null;
...@@ -1316,6 +1318,8 @@ fn buildOutputType(...@@ -1316,6 +1318,8 @@ fn buildOutputType(
1316 }1318 }
1317 } else if (mem.eql(u8, arg, "--import-memory")) {1319 } else if (mem.eql(u8, arg, "--import-memory")) {
1318 linker_import_memory = true;1320 linker_import_memory = true;
1321 } else if (mem.eql(u8, arg, "--import-symbols")) {
1322 linker_import_symbols = true;
1319 } else if (mem.eql(u8, arg, "--import-table")) {1323 } else if (mem.eql(u8, arg, "--import-table")) {
1320 linker_import_table = true;1324 linker_import_table = true;
1321 } else if (mem.eql(u8, arg, "--export-table")) {1325 } else if (mem.eql(u8, arg, "--export-table")) {
...@@ -1837,6 +1841,8 @@ fn buildOutputType(...@@ -1837,6 +1841,8 @@ fn buildOutputType(
1837 linker_bind_global_refs_locally = true;1841 linker_bind_global_refs_locally = true;
1838 } else if (mem.eql(u8, arg, "--import-memory")) {1842 } else if (mem.eql(u8, arg, "--import-memory")) {
1839 linker_import_memory = true;1843 linker_import_memory = true;
1844 } else if (mem.eql(u8, arg, "--import-symbols")) {
1845 linker_import_symbols = true;
1840 } else if (mem.eql(u8, arg, "--import-table")) {1846 } else if (mem.eql(u8, arg, "--import-table")) {
1841 linker_import_table = true;1847 linker_import_table = true;
1842 } else if (mem.eql(u8, arg, "--export-table")) {1848 } else if (mem.eql(u8, arg, "--export-table")) {
...@@ -2977,6 +2983,7 @@ fn buildOutputType(...@@ -2977,6 +2983,7 @@ fn buildOutputType(
2977 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,2983 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
2978 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,2984 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
2979 .linker_import_memory = linker_import_memory,2985 .linker_import_memory = linker_import_memory,
2986 .linker_import_symbols = linker_import_symbols,
2980 .linker_import_table = linker_import_table,2987 .linker_import_table = linker_import_table,
2981 .linker_export_table = linker_export_table,2988 .linker_export_table = linker_export_table,
2982 .linker_initial_memory = linker_initial_memory,2989 .linker_initial_memory = linker_initial_memory,