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 {
954954 linker_allow_shlib_undefined: ?bool = null,
955955 linker_bind_global_refs_locally: ?bool = null,
956956 linker_import_memory: ?bool = null,
957 linker_import_symbols: bool = false,
957958 linker_import_table: bool = false,
958959 linker_export_table: bool = false,
959960 linker_initial_memory: ?u64 = null,
......@@ -1811,6 +1812,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18111812 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
18121813 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
18131814 .import_memory = options.linker_import_memory orelse false,
1815 .import_symbols = options.linker_import_symbols,
18141816 .import_table = options.linker_import_table,
18151817 .export_table = options.linker_export_table,
18161818 .initial_memory = options.linker_initial_memory,
src/link.zig+1
......@@ -128,6 +128,7 @@ pub const Options = struct {
128128 compress_debug_sections: CompressDebugSections,
129129 bind_global_refs_locally: bool,
130130 import_memory: bool,
131 import_symbols: bool,
131132 import_table: bool,
132133 export_table: bool,
133134 initial_memory: ?u64,
src/link/Wasm.zig+3-1
......@@ -3461,8 +3461,10 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
34613461 } else if (wasm.base.options.entry == null) {
34623462 try argv.append("--no-entry"); // So lld doesn't look for _start.
34633463 }
3464 if (wasm.base.options.import_symbols) {
3465 try argv.appendSlice(&[_][]const u8{"--allow-undefined"});
3466 }
34643467 try argv.appendSlice(&[_][]const u8{
3465 "--allow-undefined",
34663468 "-o",
34673469 full_out_path,
34683470 });
src/main.zig+7
......@@ -517,6 +517,7 @@ const usage_build_generic =
517517 \\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols
518518 \\ -dead_strip_dylibs (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
519519 \\ --import-memory (WebAssembly) import memory from the environment
520 \\ --import-symbols (WebAssembly) import missing symbols from the host environment
520521 \\ --import-table (WebAssembly) import function table from the host environment
521522 \\ --export-table (WebAssembly) export function table to the host environment
522523 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory
......@@ -718,6 +719,7 @@ fn buildOutputType(
718719 var linker_allow_shlib_undefined: ?bool = null;
719720 var linker_bind_global_refs_locally: ?bool = null;
720721 var linker_import_memory: ?bool = null;
722 var linker_import_symbols: bool = false;
721723 var linker_import_table: bool = false;
722724 var linker_export_table: bool = false;
723725 var linker_initial_memory: ?u64 = null;
......@@ -1316,6 +1318,8 @@ fn buildOutputType(
13161318 }
13171319 } else if (mem.eql(u8, arg, "--import-memory")) {
13181320 linker_import_memory = true;
1321 } else if (mem.eql(u8, arg, "--import-symbols")) {
1322 linker_import_symbols = true;
13191323 } else if (mem.eql(u8, arg, "--import-table")) {
13201324 linker_import_table = true;
13211325 } else if (mem.eql(u8, arg, "--export-table")) {
......@@ -1837,6 +1841,8 @@ fn buildOutputType(
18371841 linker_bind_global_refs_locally = true;
18381842 } else if (mem.eql(u8, arg, "--import-memory")) {
18391843 linker_import_memory = true;
1844 } else if (mem.eql(u8, arg, "--import-symbols")) {
1845 linker_import_symbols = true;
18401846 } else if (mem.eql(u8, arg, "--import-table")) {
18411847 linker_import_table = true;
18421848 } else if (mem.eql(u8, arg, "--export-table")) {
......@@ -2977,6 +2983,7 @@ fn buildOutputType(
29772983 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
29782984 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
29792985 .linker_import_memory = linker_import_memory,
2986 .linker_import_symbols = linker_import_symbols,
29802987 .linker_import_table = linker_import_table,
29812988 .linker_export_table = linker_export_table,
29822989 .linker_initial_memory = linker_initial_memory,