From dd850929822abb7f81a0c4fdfa97ecf37d4bc16c Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Sun, 18 Dec 2022 16:37:00 +0100 Subject: [PATCH] wasm-linker: Fix relocations for alias'd atoms When an atom has one or multiple aliasses, we we could not find the target atom from the alias'd symbol. This is solved by ensuring that we also insert each alias symbol in the symbol-atom map. --- src/link/Wasm.zig | 36 +++++++++++++++++++++++++++--------- src/link/Wasm/Atom.zig | 6 +++++- src/link/Wasm/Object.zig | 8 ++++---- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index d8aab58ef1b5a66a0bd9aa73e9e2f221e3d1af73..6444b431be851bde10995b89778ed5a448acd684 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1568,9 +1568,13 @@ fn allocateAtoms(wasm: *Wasm) !void { var atom: *Atom = entry.value_ptr.*.getFirst(); var offset: u32 = 0; while (true) { + const symbol_loc = atom.symbolLoc(); + if (!wasm.resolved_symbols.contains(symbol_loc)) { + atom = atom.next orelse break; + continue; + } offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment); atom.offset = offset; - const symbol_loc = atom.symbolLoc(); log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{ symbol_loc.getName(wasm), offset, @@ -1578,7 +1582,7 @@ fn allocateAtoms(wasm: *Wasm) !void { atom.size, }); offset += atom.size; - try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers + try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers atom = atom.next orelse break; } segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment); @@ -2579,14 +2583,16 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l var atom: *Atom = wasm.atoms.get(code_index).?.getFirst(); // The code section must be sorted in line with the function order. - var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count()); + var sorted_atoms = try std.ArrayList(*Atom).initCapacity(gpa, wasm.functions.count()); defer sorted_atoms.deinit(); while (true) { - if (!is_obj) { - atom.resolveRelocs(wasm); + if (wasm.resolved_symbols.contains(atom.symbolLoc())) { + if (!is_obj) { + atom.resolveRelocs(wasm); + } + sorted_atoms.appendAssumeCapacity(atom); } - sorted_atoms.appendAssumeCapacity(atom); atom = atom.next orelse break; } @@ -2641,6 +2647,10 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // fill in the offset table and the data segments var current_offset: u32 = 0; while (true) { + if (!wasm.resolved_symbols.contains(atom.symbolLoc())) { + atom = atom.next orelse break; + continue; + } if (!is_obj) { atom.resolveRelocs(wasm); } @@ -4170,15 +4180,23 @@ fn emitDataRelocations( try writeCustomSectionHeader(binary_bytes.items, header_offset, size); } +pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 { + var index: u32 = 0; + while (index < wasm.func_types.items.len) : (index += 1) { + if (wasm.func_types.items[index].eql(func_type)) return index; + } + return null; +} + /// Searches for an a matching function signature, when not found /// a new entry will be made. The index of the existing/new signature will be returned. pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { - var index: u32 = 0; - while (index < wasm.func_types.items.len) : (index += 1) { - if (wasm.func_types.items[index].eql(func_type)) return index; + if (wasm.getTypeIndex(func_type)) |index| { + return index; } // functype does not exist. + const index = @intCast(u32, wasm.func_types.items.len); const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params); errdefer wasm.base.allocator.free(params); const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns); diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index f716cd56eee9160de0a15478cb3a6e31325c7593..eb3a31b8a0302224d68cf604dc55918588e89ec4 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -186,7 +186,11 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa .R_WASM_MEMORY_ADDR_SLEB, .R_WASM_MEMORY_ADDR_SLEB64, => { - std.debug.assert(symbol.tag == .data and !symbol.isUndefined()); + std.debug.assert(symbol.tag == .data); + if (symbol.isUndefined()) { + return 0; + } + const merge_segment = wasm_bin.base.options.output_mode != .Obj; const target_atom = wasm_bin.symbol_atom.get(target_loc).?; const segment_info = if (target_atom.file) |object_index| blk: { diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index e5947228a5270d5e118c4dcd384b50e452814bfd..8f49d687125bb3397aeae947837aaf5b6dec454d 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -923,7 +923,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b try atom.relocs.append(gpa, reloc); if (relocation.isTableIndex()) { - try wasm_bin.function_table.putNoClobber(gpa, .{ + try wasm_bin.function_table.put(gpa, .{ .file = object_index, .index = relocation.index, }, 0); @@ -938,17 +938,17 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b .index = relocatable_data.getIndex(), })) |symbols| { atom.sym_index = symbols.pop(); + try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom); // symbols referencing the same atom will be added as alias // or as 'parent' when they are global. while (symbols.popOrNull()) |idx| { + try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom); const alias_symbol = object.symtable[idx]; - const symbol = object.symtable[atom.sym_index]; - if (alias_symbol.isGlobal() and symbol.isLocal()) { + if (alias_symbol.isGlobal()) { atom.sym_index = idx; } } - try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom); } const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index]; -- 2.54.0