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 {...@@ -1568,9 +1568,13 @@ fn allocateAtoms(wasm: *Wasm) !void {
1568 var atom: *Atom = entry.value_ptr.*.getFirst();1568 var atom: *Atom = entry.value_ptr.*.getFirst();
1569 var offset: u32 = 0;1569 var offset: u32 = 0;
1570 while (true) {1570 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 }
1571 offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment);1576 offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment);
1572 atom.offset = offset;1577 atom.offset = offset;
1573 const symbol_loc = atom.symbolLoc();
1574 log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{1578 log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{
1575 symbol_loc.getName(wasm),1579 symbol_loc.getName(wasm),
1576 offset,1580 offset,
...@@ -1578,7 +1582,7 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1578,7 +1582,7 @@ fn allocateAtoms(wasm: *Wasm) !void {
1578 atom.size,1582 atom.size,
1579 });1583 });
1580 offset += atom.size;1584 offset += atom.size;
1581 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers1585 try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers
1582 atom = atom.next orelse break;1586 atom = atom.next orelse break;
1583 }1587 }
1584 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);1588 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...@@ -2579,14 +2583,16 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
2579 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();2583 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
25802584
2581 // The code section must be sorted in line with the function order.2585 // 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());
2583 defer sorted_atoms.deinit();2587 defer sorted_atoms.deinit();
25842588
2585 while (true) {2589 while (true) {
2586 if (!is_obj) {2590 if (wasm.resolved_symbols.contains(atom.symbolLoc())) {
2587 atom.resolveRelocs(wasm);2591 if (!is_obj) {
2592 atom.resolveRelocs(wasm);
2593 }
2594 sorted_atoms.appendAssumeCapacity(atom);
2588 }2595 }
2589 sorted_atoms.appendAssumeCapacity(atom);
2590 atom = atom.next orelse break;2596 atom = atom.next orelse break;
2591 }2597 }
25922598
...@@ -2641,6 +2647,10 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -2641,6 +2647,10 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
2641 // fill in the offset table and the data segments2647 // fill in the offset table and the data segments
2642 var current_offset: u32 = 0;2648 var current_offset: u32 = 0;
2643 while (true) {2649 while (true) {
2650 if (!wasm.resolved_symbols.contains(atom.symbolLoc())) {
2651 atom = atom.next orelse break;
2652 continue;
2653 }
2644 if (!is_obj) {2654 if (!is_obj) {
2645 atom.resolveRelocs(wasm);2655 atom.resolveRelocs(wasm);
2646 }2656 }
...@@ -4170,15 +4180,23 @@ fn emitDataRelocations(...@@ -4170,15 +4180,23 @@ fn emitDataRelocations(
4170 try writeCustomSectionHeader(binary_bytes.items, header_offset, size);4180 try writeCustomSectionHeader(binary_bytes.items, header_offset, size);
4171}4181}
41724182
4173/// Searches for an a matching function signature, when not found4183pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 {
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 {
4176 var index: u32 = 0;4184 var index: u32 = 0;
4177 while (index < wasm.func_types.items.len) : (index += 1) {4185 while (index < wasm.func_types.items.len) : (index += 1) {
4178 if (wasm.func_types.items[index].eql(func_type)) return index;4186 if (wasm.func_types.items[index].eql(func_type)) return index;
4179 }4187 }
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
4181 // functype does not exist.4198 // functype does not exist.
4199 const index = @intCast(u32, wasm.func_types.items.len);
4182 const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);4200 const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);
4183 errdefer wasm.base.allocator.free(params);4201 errdefer wasm.base.allocator.free(params);
4184 const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns);4202 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...@@ -186,7 +186,11 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
186 .R_WASM_MEMORY_ADDR_SLEB,186 .R_WASM_MEMORY_ADDR_SLEB,
187 .R_WASM_MEMORY_ADDR_SLEB64,187 .R_WASM_MEMORY_ADDR_SLEB64,
188 => {188 => {
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
190 const merge_segment = wasm_bin.base.options.output_mode != .Obj;194 const merge_segment = wasm_bin.base.options.output_mode != .Obj;
191 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;195 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
192 const segment_info = if (target_atom.file) |object_index| blk: {196 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...@@ -923,7 +923,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
923 try atom.relocs.append(gpa, reloc);923 try atom.relocs.append(gpa, reloc);
924924
925 if (relocation.isTableIndex()) {925 if (relocation.isTableIndex()) {
926 try wasm_bin.function_table.putNoClobber(gpa, .{926 try wasm_bin.function_table.put(gpa, .{
927 .file = object_index,927 .file = object_index,
928 .index = relocation.index,928 .index = relocation.index,
929 }, 0);929 }, 0);
...@@ -938,17 +938,17 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b...@@ -938,17 +938,17 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
938 .index = relocatable_data.getIndex(),938 .index = relocatable_data.getIndex(),
939 })) |symbols| {939 })) |symbols| {
940 atom.sym_index = symbols.pop();940 atom.sym_index = symbols.pop();
941 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
941942
942 // symbols referencing the same atom will be added as alias943 // symbols referencing the same atom will be added as alias
943 // or as 'parent' when they are global.944 // or as 'parent' when they are global.
944 while (symbols.popOrNull()) |idx| {945 while (symbols.popOrNull()) |idx| {
946 try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom);
945 const alias_symbol = object.symtable[idx];947 const alias_symbol = object.symtable[idx];
946 const symbol = object.symtable[atom.sym_index];948 if (alias_symbol.isGlobal()) {
947 if (alias_symbol.isGlobal() and symbol.isLocal()) {
948 atom.sym_index = idx;949 atom.sym_index = idx;
949 }950 }
950 }951 }
951 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
952 }952 }
953953
954 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];954 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];