diff options
| author | Luuk de Gram <luuk@degram.dev> | 2023-01-09 19:22:55 +0100 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2023-01-12 20:50:15 +0100 |
| commit | 2339b25fd42ccd136660b9e4575aab2bb85b1163 (patch) | |
| tree | 490b3011197f7dc8fe5f4c3f320cb9c0f5e72737 /src | |
| parent | cbbf8c8a2d77d84ce88ea1cef9a3e7d54081e33d (diff) | |
| download | zig-2339b25fd42ccd136660b9e4575aab2bb85b1163.tar.gz zig-2339b25fd42ccd136660b9e4575aab2bb85b1163.zip | |
wasm-linker: discard symbol when both undefined
During symbol resolution when both symbols are undefined, we must
discard the new symbol with a reference to the existing symbol. This
ensures the original symbol remains undefined. This fixes symbol
resolution when linking with WASI-libC.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Wasm.zig | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index d62d5adb25..377d526249 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -600,27 +600,34 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { } if (existing_sym.isUndefined() and symbol.isUndefined()) { - const existing_name = if (existing_loc.file) |file_index| blk: { - const obj = wasm.objects.items[file_index]; - const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name; - break :blk obj.string_table.get(name_index); - } else blk: { - const name_index = wasm.imports.get(existing_loc).?.module_name; - break :blk wasm.string_table.get(name_index); - }; + // only verify module/import name for function symbols + if (symbol.tag == .function) { + const existing_name = if (existing_loc.file) |file_index| blk: { + const obj = wasm.objects.items[file_index]; + const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name; + break :blk obj.string_table.get(name_index); + } else blk: { + const name_index = wasm.imports.get(existing_loc).?.module_name; + break :blk wasm.string_table.get(name_index); + }; - const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name; - const module_name = object.string_table.get(module_index); - if (!mem.eql(u8, existing_name, module_name)) { - log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{ - sym_name, - existing_name, - module_name, - }); - log.err(" first definition in '{s}'", .{existing_file_path}); - log.err(" next definition in '{s}'", .{object.name}); - return error.ModuleNameMismatch; + const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name; + const module_name = object.string_table.get(module_index); + if (!mem.eql(u8, existing_name, module_name)) { + log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{ + sym_name, + existing_name, + module_name, + }); + log.err(" first definition in '{s}'", .{existing_file_path}); + log.err(" next definition in '{s}'", .{object.name}); + return error.ModuleNameMismatch; + } } + + // both undefined so skip overwriting existing symbol and discard the new symbol + try wasm.discarded.put(wasm.base.allocator, location, existing_loc); + continue; } if (existing_sym.tag == .global) { @@ -646,8 +653,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { } } - // when both symbols are weak, we skip overwriting - if (existing_sym.isWeak() and symbol.isWeak()) { + // when both symbols are weak, we skip overwriting unless the existing + // symbol is weak and the new one isn't, in which case we *do* overwrite it. + if (existing_sym.isWeak() and symbol.isWeak()) blk: { + if (existing_sym.isUndefined() and !symbol.isUndefined()) break :blk; try wasm.discarded.put(wasm.base.allocator, location, existing_loc); continue; } @@ -1935,7 +1944,9 @@ fn setupStart(wasm: *Wasm) !void { return error.MissingSymbol; }; - const symbol_loc = wasm.globals.get(symbol_name_offset).?; + const symbol_loc = wasm.globals.get(symbol_name_offset) orelse { + log.err("Entry symbol '{s}' not found", .{entry_name}); + }; const symbol = symbol_loc.getSymbol(wasm); if (symbol.tag != .function) { log.err("Entry symbol '{s}' is not a function", .{entry_name}); |
