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 {...@@ -111,7 +111,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
111 .R_WASM_GLOBAL_INDEX_I32,111 .R_WASM_GLOBAL_INDEX_I32,
112 .R_WASM_MEMORY_ADDR_I32,112 .R_WASM_MEMORY_ADDR_I32,
113 .R_WASM_SECTION_OFFSET_I32,113 .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),
115 .R_WASM_TABLE_INDEX_I64,115 .R_WASM_TABLE_INDEX_I64,
116 .R_WASM_MEMORY_ADDR_I64,116 .R_WASM_MEMORY_ADDR_I64,
117 => std.mem.writeInt(u64, atom.code.items[reloc.offset - atom.original_offset ..][0..8], value, .little),117 => 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 {...@@ -124,7 +124,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
124 .R_WASM_TABLE_NUMBER_LEB,124 .R_WASM_TABLE_NUMBER_LEB,
125 .R_WASM_TYPE_INDEX_LEB,125 .R_WASM_TYPE_INDEX_LEB,
126 .R_WASM_MEMORY_ADDR_TLS_SLEB,126 .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))),
128 .R_WASM_MEMORY_ADDR_LEB64,128 .R_WASM_MEMORY_ADDR_LEB64,
129 .R_WASM_MEMORY_ADDR_SLEB64,129 .R_WASM_MEMORY_ADDR_SLEB64,
130 .R_WASM_TABLE_INDEX_SLEB64,130 .R_WASM_TABLE_INDEX_SLEB64,
...@@ -140,6 +140,13 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {...@@ -140,6 +140,13 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
140fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {140fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
141 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);141 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
142 const symbol = target_loc.getSymbol(wasm_bin);142 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 }
143 switch (relocation.relocation_type) {150 switch (relocation.relocation_type) {
144 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,151 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,
145 .R_WASM_TABLE_NUMBER_LEB => return symbol.index,152 .R_WASM_TABLE_NUMBER_LEB => return symbol.index,
...@@ -170,30 +177,43 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -170,30 +177,43 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
170 if (symbol.isUndefined()) {177 if (symbol.isUndefined()) {
171 return 0;178 return 0;
172 }179 }
173 const va = @as(i64, @intCast(symbol.virtual_address));180 const va: i33 = @intCast(symbol.virtual_address);
174 return @intCast(va + relocation.addend);181 return @intCast(va + relocation.addend);
175 },182 },
176 .R_WASM_EVENT_INDEX_LEB => return symbol.index,183 .R_WASM_EVENT_INDEX_LEB => return symbol.index,
177 .R_WASM_SECTION_OFFSET_I32 => {184 .R_WASM_SECTION_OFFSET_I32 => {
178 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;185 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
179 const target_atom = wasm_bin.getAtom(target_atom_index);186 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);
181 return @intCast(rel_value + relocation.addend);188 return @intCast(rel_value + relocation.addend);
182 },189 },
183 .R_WASM_FUNCTION_OFFSET_I32 => {190 .R_WASM_FUNCTION_OFFSET_I32 => {
184 const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {191 if (symbol.isUndefined()) {
185 return @as(u32, @bitCast(@as(i32, -1)));192 const val = atom.thombstone(wasm_bin) orelse relocation.addend;
186 };193 return @bitCast(val);
194 }
195 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
187 const target_atom = wasm_bin.getAtom(target_atom_index);196 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)197 const rel_value: i33 = @intCast(target_atom.offset);
189 const rel_value: i32 = @intCast(target_atom.offset + offset);
190 return @intCast(rel_value + relocation.addend);198 return @intCast(rel_value + relocation.addend);
191 },199 },
192 .R_WASM_MEMORY_ADDR_TLS_SLEB,200 .R_WASM_MEMORY_ADDR_TLS_SLEB,
193 .R_WASM_MEMORY_ADDR_TLS_SLEB64,201 .R_WASM_MEMORY_ADDR_TLS_SLEB64,
194 => {202 => {
195 const va: i32 = @intCast(symbol.virtual_address);203 const va: i33 = @intCast(symbol.virtual_address);
196 return @intCast(va + relocation.addend);204 return @intCast(va + relocation.addend);
197 },205 },
198 }206 }
199}207}
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}