authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-01-10 06:55:12+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-01-12 14:57:37+01:00
log3f22bb96f393a81a33772bdeddce5fc660e4f667
treef9745fdbf2053f283598db808e7304a82ec13df9
parent7fe629a8124f27e8db01e090031a5243a452e831
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: fix debug info relocation

This corrects calculating the offsets to the code section as we now correctly allocate the code atoms during write taking the 'size' into account. We also handle dead symbols which are garbage-collected by writing -2 and -1 to skip ranges, loc and other sections respectively.

1 files changed, 30 insertions(+), 10 deletions(-)

src/link/Wasm/Atom.zig+30-10
......@@ -111,7 +111,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
111111 .R_WASM_GLOBAL_INDEX_I32,
112112 .R_WASM_MEMORY_ADDR_I32,
113113 .R_WASM_SECTION_OFFSET_I32,
114 => std.mem.writeInt(u32, atom.code.items[reloc.offset - atom.original_offset ..][0..4], @as(u32, @intCast(value)), .little),
114 => std.mem.writeInt(u32, atom.code.items[reloc.offset - atom.original_offset ..][0..4], @as(u32, @truncate(value)), .little),
115115 .R_WASM_TABLE_INDEX_I64,
116116 .R_WASM_MEMORY_ADDR_I64,
117117 => std.mem.writeInt(u64, atom.code.items[reloc.offset - atom.original_offset ..][0..8], value, .little),
......@@ -124,7 +124,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
124124 .R_WASM_TABLE_NUMBER_LEB,
125125 .R_WASM_TYPE_INDEX_LEB,
126126 .R_WASM_MEMORY_ADDR_TLS_SLEB,
127 => leb.writeUnsignedFixed(5, atom.code.items[reloc.offset - atom.original_offset ..][0..5], @as(u32, @intCast(value))),
127 => leb.writeUnsignedFixed(5, atom.code.items[reloc.offset - atom.original_offset ..][0..5], @as(u32, @truncate(value))),
128128 .R_WASM_MEMORY_ADDR_LEB64,
129129 .R_WASM_MEMORY_ADDR_SLEB64,
130130 .R_WASM_TABLE_INDEX_SLEB64,
......@@ -140,6 +140,13 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
140140fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
141141 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
142142 const symbol = target_loc.getSymbol(wasm_bin);
143 if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and
144 symbol.tag != .section and
145 symbol.isDead())
146 {
147 const val = atom.thombstone(wasm_bin) orelse relocation.addend;
148 return @bitCast(val);
149 }
143150 switch (relocation.relocation_type) {
144151 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,
145152 .R_WASM_TABLE_NUMBER_LEB => return symbol.index,
......@@ -170,30 +177,43 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
170177 if (symbol.isUndefined()) {
171178 return 0;
172179 }
173 const va = @as(i64, @intCast(symbol.virtual_address));
180 const va: i33 = @intCast(symbol.virtual_address);
174181 return @intCast(va + relocation.addend);
175182 },
176183 .R_WASM_EVENT_INDEX_LEB => return symbol.index,
177184 .R_WASM_SECTION_OFFSET_I32 => {
178185 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
179186 const target_atom = wasm_bin.getAtom(target_atom_index);
180 const rel_value: i32 = @intCast(target_atom.offset);
187 const rel_value: i33 = @intCast(target_atom.offset);
181188 return @intCast(rel_value + relocation.addend);
182189 },
183190 .R_WASM_FUNCTION_OFFSET_I32 => {
184 const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {
185 return @as(u32, @bitCast(@as(i32, -1)));
186 };
191 if (symbol.isUndefined()) {
192 const val = atom.thombstone(wasm_bin) orelse relocation.addend;
193 return @bitCast(val);
194 }
195 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
187196 const target_atom = wasm_bin.getAtom(target_atom_index);
188 const offset: u32 = 11 + Wasm.getULEB128Size(target_atom.size); // Header (11 bytes fixed-size) + body size (leb-encoded)
189 const rel_value: i32 = @intCast(target_atom.offset + offset);
197 const rel_value: i33 = @intCast(target_atom.offset);
190198 return @intCast(rel_value + relocation.addend);
191199 },
192200 .R_WASM_MEMORY_ADDR_TLS_SLEB,
193201 .R_WASM_MEMORY_ADDR_TLS_SLEB64,
194202 => {
195 const va: i32 = @intCast(symbol.virtual_address);
203 const va: i33 = @intCast(symbol.virtual_address);
196204 return @intCast(va + relocation.addend);
197205 },
198206 }
199207}
208
209// For a given `Atom` returns whether it has a thombstone value or not.
210/// This defines whether we want a specific value when a section is dead.
211fn thombstone(atom: Atom, wasm: *const Wasm) ?i64 {
212 const atom_name = atom.symbolLoc().getName(wasm);
213 if (std.mem.eql(u8, atom_name, ".debug_ranges") or std.mem.eql(u8, atom_name, ".debug_loc")) {
214 return -2;
215 } else if (std.mem.startsWith(u8, atom_name, ".debug_")) {
216 return -1;
217 }
218 return null;
219}