aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-01-09 19:22:55 +0100
committerLuuk de Gram <luuk@degram.dev>2023-01-12 20:50:15 +0100
commit2339b25fd42ccd136660b9e4575aab2bb85b1163 (patch)
tree490b3011197f7dc8fe5f4c3f320cb9c0f5e72737 /src
parentcbbf8c8a2d77d84ce88ea1cef9a3e7d54081e33d (diff)
downloadzig-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.zig55
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});