authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-10-08 11:00:07+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-08 17:23:13+02:00
log7f508480f49b78817bf67579a8810d4499cbbc13
treed1f9dbed875ae37d2ebf5997cc0d2cde9e3bdfa0
parentfa9327ac051031be21b6ccb494f31585d0b68915

wasm-linker: convert relocation addend to i32

Addends in relocations are signed integers as theoretically it could be a negative number. As Atom's offsets are relative to their parent section, the relocation value should still result in a postive number. For this reason, the final result is stored as an unsigned integer. Also, rather than using `null` for relocations that do not support addends. We set the value to 0 for those that do not support addends, and have to call `addendIsPresent` to determine if an addend exists or not. This means each Relocation costs 4 bytes less than before, saving memory while linking.

5 files changed, 14 insertions(+), 11 deletions(-)

src/arch/wasm/Emit.zig+1-1
...@@ -413,7 +413,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -413,7 +413,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
413 .offset = mem_offset,413 .offset = mem_offset,
414 .index = mem.pointer,414 .index = mem.pointer,
415 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64,415 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64,
416 .addend = mem.offset,416 .addend = @intCast(i32, mem.offset),
417 });417 });
418 }418 }
419}419}
src/link/Wasm.zig+4-4
...@@ -1080,7 +1080,7 @@ pub fn getDeclVAddr(...@@ -1080,7 +1080,7 @@ pub fn getDeclVAddr(
1080 .index = target_symbol_index,1080 .index = target_symbol_index,
1081 .offset = @intCast(u32, reloc_info.offset),1081 .offset = @intCast(u32, reloc_info.offset),
1082 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,1082 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
1083 .addend = reloc_info.addend,1083 .addend = @intCast(i32, reloc_info.addend),
1084 });1084 });
1085 }1085 }
1086 // we do not know the final address at this point,1086 // we do not know the final address at this point,
...@@ -2001,7 +2001,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -2001,7 +2001,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
2001 .index = names_symbol_index,2001 .index = names_symbol_index,
2002 .relocation_type = .R_WASM_MEMORY_ADDR_I32,2002 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
2003 .offset = offset,2003 .offset = offset,
2004 .addend = addend,2004 .addend = @intCast(i32, addend),
2005 });2005 });
2006 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));2006 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));
2007 addend += len;2007 addend += len;
...@@ -3433,7 +3433,7 @@ fn emitCodeRelocations(...@@ -3433,7 +3433,7 @@ fn emitCodeRelocations(
3433 try leb.writeULEB128(writer, offset);3433 try leb.writeULEB128(writer, offset);
3434 try leb.writeULEB128(writer, symbol_index);3434 try leb.writeULEB128(writer, symbol_index);
3435 if (relocation.relocation_type.addendIsPresent()) {3435 if (relocation.relocation_type.addendIsPresent()) {
3436 try leb.writeULEB128(writer, relocation.addend orelse 0);3436 try leb.writeILEB128(writer, relocation.addend);
3437 }3437 }
3438 log.debug("Emit relocation: {}", .{relocation});3438 log.debug("Emit relocation: {}", .{relocation});
3439 }3439 }
...@@ -3483,7 +3483,7 @@ fn emitDataRelocations(...@@ -3483,7 +3483,7 @@ fn emitDataRelocations(
3483 try leb.writeULEB128(writer, offset);3483 try leb.writeULEB128(writer, offset);
3484 try leb.writeULEB128(writer, symbol_index);3484 try leb.writeULEB128(writer, symbol_index);
3485 if (relocation.relocation_type.addendIsPresent()) {3485 if (relocation.relocation_type.addendIsPresent()) {
3486 try leb.writeULEB128(writer, relocation.addend orelse 0);3486 try leb.writeILEB128(writer, relocation.addend);
3487 }3487 }
3488 log.debug("Emit relocation: {}", .{relocation});3488 log.debug("Emit relocation: {}", .{relocation});
3489 }3489 }
src/link/Wasm/Atom.zig+6-3
...@@ -194,12 +194,14 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -194,12 +194,14 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
194 const segment_name = segment_info[symbol.index].outputName(merge_segment);194 const segment_name = segment_info[symbol.index].outputName(merge_segment);
195 const segment_index = wasm_bin.data_segments.get(segment_name).?;195 const segment_index = wasm_bin.data_segments.get(segment_name).?;
196 const segment = wasm_bin.segments.items[segment_index];196 const segment = wasm_bin.segments.items[segment_index];
197 return target_atom.offset + segment.offset + (relocation.addend orelse 0);197 const rel_value = @intCast(i32, target_atom.offset + segment.offset) + relocation.addend;
198 return @intCast(u32, rel_value);
198 },199 },
199 .R_WASM_EVENT_INDEX_LEB => return symbol.index,200 .R_WASM_EVENT_INDEX_LEB => return symbol.index,
200 .R_WASM_SECTION_OFFSET_I32 => {201 .R_WASM_SECTION_OFFSET_I32 => {
201 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;202 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
202 return target_atom.offset + (relocation.addend orelse 0);203 const rel_value = @intCast(i32, target_atom.offset) + relocation.addend;
204 return @intCast(u32, rel_value);
203 },205 },
204 .R_WASM_FUNCTION_OFFSET_I32 => {206 .R_WASM_FUNCTION_OFFSET_I32 => {
205 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;207 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
...@@ -214,7 +216,8 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -214,7 +216,8 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
214 if (current_atom == target_atom) break;216 if (current_atom == target_atom) break;
215 current_atom = current_atom.next.?;217 current_atom = current_atom.next.?;
216 }218 }
217 return target_atom.offset + offset + (relocation.addend orelse 0);219 const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend;
220 return @intCast(u32, rel_value);
218 },221 },
219 }222 }
220}223}
src/link/Wasm/Object.zig+1-1
...@@ -606,7 +606,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -606,7 +606,7 @@ fn Parser(comptime ReaderType: type) type {
606 .relocation_type = rel_type_enum,606 .relocation_type = rel_type_enum,
607 .offset = try leb.readULEB128(u32, reader),607 .offset = try leb.readULEB128(u32, reader),
608 .index = try leb.readULEB128(u32, reader),608 .index = try leb.readULEB128(u32, reader),
609 .addend = if (rel_type_enum.addendIsPresent()) try leb.readULEB128(u32, reader) else null,609 .addend = if (rel_type_enum.addendIsPresent()) try leb.readILEB128(i32, reader) else 0,
610 };610 };
611 log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{611 log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{
612 @tagName(relocation.relocation_type),612 @tagName(relocation.relocation_type),
src/link/Wasm/types.zig+2-2
...@@ -12,8 +12,8 @@ pub const Relocation = struct {...@@ -12,8 +12,8 @@ pub const Relocation = struct {
12 /// When the type is `R_WASM_TYPE_INDEX_LEB`, it represents the index of the type.12 /// When the type is `R_WASM_TYPE_INDEX_LEB`, it represents the index of the type.
13 index: u32,13 index: u32,
14 /// Addend to add to the address.14 /// Addend to add to the address.
15 /// This field is only non-null for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`.15 /// This field is only non-zero for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`.
16 addend: ?u32 = null,16 addend: i32 = 0,
1717
18 /// All possible relocation types currently existing.18 /// All possible relocation types currently existing.
19 /// This enum is exhaustive as the spec is WIP and new types19 /// This enum is exhaustive as the spec is WIP and new types