authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-01-09 19:22:55+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-01-12 20:50:15+01:00
log2339b25fd42ccd136660b9e4575aab2bb85b1163
tree490b3011197f7dc8fe5f4c3f320cb9c0f5e72737
parentcbbf8c8a2d77d84ce88ea1cef9a3e7d54081e33d
signature Commit is signed but in an unrecognized format.

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.

1 files changed, 33 insertions(+), 22 deletions(-)

src/link/Wasm.zig+33-22
...@@ -600,27 +600,34 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -600,27 +600,34 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
600 }600 }
601601
602 if (existing_sym.isUndefined() and symbol.isUndefined()) {602 if (existing_sym.isUndefined() and symbol.isUndefined()) {
603 const existing_name = if (existing_loc.file) |file_index| blk: {603 // only verify module/import name for function symbols
604 const obj = wasm.objects.items[file_index];604 if (symbol.tag == .function) {
605 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;605 const existing_name = if (existing_loc.file) |file_index| blk: {
606 break :blk obj.string_table.get(name_index);606 const obj = wasm.objects.items[file_index];
607 } else blk: {607 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;
608 const name_index = wasm.imports.get(existing_loc).?.module_name;608 break :blk obj.string_table.get(name_index);
609 break :blk wasm.string_table.get(name_index);609 } else blk: {
610 };610 const name_index = wasm.imports.get(existing_loc).?.module_name;
611 break :blk wasm.string_table.get(name_index);
612 };
611613
612 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;614 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;
613 const module_name = object.string_table.get(module_index);615 const module_name = object.string_table.get(module_index);
614 if (!mem.eql(u8, existing_name, module_name)) {616 if (!mem.eql(u8, existing_name, module_name)) {
615 log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{617 log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{
616 sym_name,618 sym_name,
617 existing_name,619 existing_name,
618 module_name,620 module_name,
619 });621 });
620 log.err(" first definition in '{s}'", .{existing_file_path});622 log.err(" first definition in '{s}'", .{existing_file_path});
621 log.err(" next definition in '{s}'", .{object.name});623 log.err(" next definition in '{s}'", .{object.name});
622 return error.ModuleNameMismatch;624 return error.ModuleNameMismatch;
625 }
623 }626 }
627
628 // both undefined so skip overwriting existing symbol and discard the new symbol
629 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);
630 continue;
624 }631 }
625632
626 if (existing_sym.tag == .global) {633 if (existing_sym.tag == .global) {
...@@ -646,8 +653,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -646,8 +653,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
646 }653 }
647 }654 }
648655
649 // when both symbols are weak, we skip overwriting656 // when both symbols are weak, we skip overwriting unless the existing
650 if (existing_sym.isWeak() and symbol.isWeak()) {657 // symbol is weak and the new one isn't, in which case we *do* overwrite it.
658 if (existing_sym.isWeak() and symbol.isWeak()) blk: {
659 if (existing_sym.isUndefined() and !symbol.isUndefined()) break :blk;
651 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);660 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);
652 continue;661 continue;
653 }662 }
...@@ -1935,7 +1944,9 @@ fn setupStart(wasm: *Wasm) !void {...@@ -1935,7 +1944,9 @@ fn setupStart(wasm: *Wasm) !void {
1935 return error.MissingSymbol;1944 return error.MissingSymbol;
1936 };1945 };
19371946
1938 const symbol_loc = wasm.globals.get(symbol_name_offset).?;1947 const symbol_loc = wasm.globals.get(symbol_name_offset) orelse {
1948 log.err("Entry symbol '{s}' not found", .{entry_name});
1949 };
1939 const symbol = symbol_loc.getSymbol(wasm);1950 const symbol = symbol_loc.getSymbol(wasm);
1940 if (symbol.tag != .function) {1951 if (symbol.tag != .function) {
1941 log.err("Entry symbol '{s}' is not a function", .{entry_name});1952 log.err("Entry symbol '{s}' is not a function", .{entry_name});