From 7f508480f49b78817bf67579a8810d4499cbbc13 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Sat, 8 Oct 2022 11:00:07 +0200 Subject: [PATCH] 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. --- src/arch/wasm/Emit.zig | 2 +- src/link/Wasm.zig | 8 ++++---- src/link/Wasm/Atom.zig | 9 ++++++--- src/link/Wasm/Object.zig | 2 +- src/link/Wasm/types.zig | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 0f3ee9a2a29b908f88caad441964b51653566412..ed8501a601e5b389adfefad230db90940dbfaf0e 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -413,7 +413,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { .offset = mem_offset, .index = mem.pointer, .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64, - .addend = mem.offset, + .addend = @intCast(i32, mem.offset), }); } } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index b808653107c9e2231103eb48ee78ba69150275cd..2327837b3144c55710a198cf7449404e80f4d26c 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1080,7 +1080,7 @@ pub fn getDeclVAddr( .index = target_symbol_index, .offset = @intCast(u32, reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, - .addend = reloc_info.addend, + .addend = @intCast(i32, reloc_info.addend), }); } // we do not know the final address at this point, @@ -2001,7 +2001,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { .index = names_symbol_index, .relocation_type = .R_WASM_MEMORY_ADDR_I32, .offset = offset, - .addend = addend, + .addend = @intCast(i32, addend), }); atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target)); addend += len; @@ -3433,7 +3433,7 @@ fn emitCodeRelocations( try leb.writeULEB128(writer, offset); try leb.writeULEB128(writer, symbol_index); if (relocation.relocation_type.addendIsPresent()) { - try leb.writeULEB128(writer, relocation.addend orelse 0); + try leb.writeILEB128(writer, relocation.addend); } log.debug("Emit relocation: {}", .{relocation}); } @@ -3483,7 +3483,7 @@ fn emitDataRelocations( try leb.writeULEB128(writer, offset); try leb.writeULEB128(writer, symbol_index); if (relocation.relocation_type.addendIsPresent()) { - try leb.writeULEB128(writer, relocation.addend orelse 0); + try leb.writeILEB128(writer, relocation.addend); } log.debug("Emit relocation: {}", .{relocation}); } diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index 5af07d891a3e841f38013d544eed233939d4be93..4c1da180bd092034056f5e8b14b7c8e91537b1fb 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -194,12 +194,14 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa const segment_name = segment_info[symbol.index].outputName(merge_segment); const segment_index = wasm_bin.data_segments.get(segment_name).?; const segment = wasm_bin.segments.items[segment_index]; - return target_atom.offset + segment.offset + (relocation.addend orelse 0); + const rel_value = @intCast(i32, target_atom.offset + segment.offset) + relocation.addend; + return @intCast(u32, rel_value); }, .R_WASM_EVENT_INDEX_LEB => return symbol.index, .R_WASM_SECTION_OFFSET_I32 => { const target_atom = wasm_bin.symbol_atom.get(target_loc).?; - return target_atom.offset + (relocation.addend orelse 0); + const rel_value = @intCast(i32, target_atom.offset) + relocation.addend; + return @intCast(u32, rel_value); }, .R_WASM_FUNCTION_OFFSET_I32 => { 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 if (current_atom == target_atom) break; current_atom = current_atom.next.?; } - return target_atom.offset + offset + (relocation.addend orelse 0); + const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend; + return @intCast(u32, rel_value); }, } } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 97b7da0255a7ed02d24a4c1861442a2c3624b224..63084f487946b3e803fc509e7afe133b68c35539 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -606,7 +606,7 @@ fn Parser(comptime ReaderType: type) type { .relocation_type = rel_type_enum, .offset = try leb.readULEB128(u32, reader), .index = try leb.readULEB128(u32, reader), - .addend = if (rel_type_enum.addendIsPresent()) try leb.readULEB128(u32, reader) else null, + .addend = if (rel_type_enum.addendIsPresent()) try leb.readILEB128(i32, reader) else 0, }; log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{ @tagName(relocation.relocation_type), diff --git a/src/link/Wasm/types.zig b/src/link/Wasm/types.zig index 9216f95efa1e224129d774138a78db02c6abb226..2006fe1812551ea61380dd5f507095610d3d4718 100644 --- a/src/link/Wasm/types.zig +++ b/src/link/Wasm/types.zig @@ -12,8 +12,8 @@ pub const Relocation = struct { /// When the type is `R_WASM_TYPE_INDEX_LEB`, it represents the index of the type. index: u32, /// Addend to add to the address. - /// This field is only non-null for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`. - addend: ?u32 = null, + /// This field is only non-zero for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`. + addend: i32 = 0, /// All possible relocation types currently existing. /// This enum is exhaustive as the spec is WIP and new types -- 2.54.0