authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-12-18 16:37:00+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-12-18 16:37:00+01:00
logdd850929822abb7f81a0c4fdfa97ecf37d4bc16c
tree805ac327e4864f151b348cd162dc784906c1aa8d
parent2a62dbda0bb5e5c8a1c92a058b684309bd7efeeb
signaturelock-open Commit is signed but in an unrecognized format.

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.

3 files changed, 36 insertions(+), 14 deletions(-)

src/link/Wasm.zig+27-9
......@@ -1568,9 +1568,13 @@ fn allocateAtoms(wasm: *Wasm) !void {
15681568 var atom: *Atom = entry.value_ptr.*.getFirst();
15691569 var offset: u32 = 0;
15701570 while (true) {
1571 const symbol_loc = atom.symbolLoc();
1572 if (!wasm.resolved_symbols.contains(symbol_loc)) {
1573 atom = atom.next orelse break;
1574 continue;
1575 }
15711576 offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment);
15721577 atom.offset = offset;
1573 const symbol_loc = atom.symbolLoc();
15741578 log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{
15751579 symbol_loc.getName(wasm),
15761580 offset,
......@@ -1578,7 +1582,7 @@ fn allocateAtoms(wasm: *Wasm) !void {
15781582 atom.size,
15791583 });
15801584 offset += atom.size;
1581 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers
1585 try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers
15821586 atom = atom.next orelse break;
15831587 }
15841588 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
25792583 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
25802584
25812585 // The code section must be sorted in line with the function order.
2582 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count());
2586 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(gpa, wasm.functions.count());
25832587 defer sorted_atoms.deinit();
25842588
25852589 while (true) {
2586 if (!is_obj) {
2587 atom.resolveRelocs(wasm);
2590 if (wasm.resolved_symbols.contains(atom.symbolLoc())) {
2591 if (!is_obj) {
2592 atom.resolveRelocs(wasm);
2593 }
2594 sorted_atoms.appendAssumeCapacity(atom);
25882595 }
2589 sorted_atoms.appendAssumeCapacity(atom);
25902596 atom = atom.next orelse break;
25912597 }
25922598
......@@ -2641,6 +2647,10 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
26412647 // fill in the offset table and the data segments
26422648 var current_offset: u32 = 0;
26432649 while (true) {
2650 if (!wasm.resolved_symbols.contains(atom.symbolLoc())) {
2651 atom = atom.next orelse break;
2652 continue;
2653 }
26442654 if (!is_obj) {
26452655 atom.resolveRelocs(wasm);
26462656 }
......@@ -4170,15 +4180,23 @@ fn emitDataRelocations(
41704180 try writeCustomSectionHeader(binary_bytes.items, header_offset, size);
41714181}
41724182
4173/// Searches for an a matching function signature, when not found
4174/// a new entry will be made. The index of the existing/new signature will be returned.
4175pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 {
4183pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 {
41764184 var index: u32 = 0;
41774185 while (index < wasm.func_types.items.len) : (index += 1) {
41784186 if (wasm.func_types.items[index].eql(func_type)) return index;
41794187 }
4188 return null;
4189}
4190
4191/// Searches for an a matching function signature, when not found
4192/// a new entry will be made. The index of the existing/new signature will be returned.
4193pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 {
4194 if (wasm.getTypeIndex(func_type)) |index| {
4195 return index;
4196 }
41804197
41814198 // functype does not exist.
4199 const index = @intCast(u32, wasm.func_types.items.len);
41824200 const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);
41834201 errdefer wasm.base.allocator.free(params);
41844202 const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns);
src/link/Wasm/Atom.zig+5-1
......@@ -186,7 +186,11 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
186186 .R_WASM_MEMORY_ADDR_SLEB,
187187 .R_WASM_MEMORY_ADDR_SLEB64,
188188 => {
189 std.debug.assert(symbol.tag == .data and !symbol.isUndefined());
189 std.debug.assert(symbol.tag == .data);
190 if (symbol.isUndefined()) {
191 return 0;
192 }
193
190194 const merge_segment = wasm_bin.base.options.output_mode != .Obj;
191195 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
192196 const segment_info = if (target_atom.file) |object_index| blk: {
src/link/Wasm/Object.zig+4-4
......@@ -923,7 +923,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
923923 try atom.relocs.append(gpa, reloc);
924924
925925 if (relocation.isTableIndex()) {
926 try wasm_bin.function_table.putNoClobber(gpa, .{
926 try wasm_bin.function_table.put(gpa, .{
927927 .file = object_index,
928928 .index = relocation.index,
929929 }, 0);
......@@ -938,17 +938,17 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
938938 .index = relocatable_data.getIndex(),
939939 })) |symbols| {
940940 atom.sym_index = symbols.pop();
941 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
941942
942943 // symbols referencing the same atom will be added as alias
943944 // or as 'parent' when they are global.
944945 while (symbols.popOrNull()) |idx| {
946 try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom);
945947 const alias_symbol = object.symtable[idx];
946 const symbol = object.symtable[atom.sym_index];
947 if (alias_symbol.isGlobal() and symbol.isLocal()) {
948 if (alias_symbol.isGlobal()) {
948949 atom.sym_index = idx;
949950 }
950951 }
951 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
952952 }
953953
954954 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];