diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index cdf22378b7..c8d115b872 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -111,7 +111,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { .R_WASM_GLOBAL_INDEX_I32, .R_WASM_MEMORY_ADDR_I32, .R_WASM_SECTION_OFFSET_I32, - => std.mem.writeInt(u32, atom.code.items[reloc.offset - atom.original_offset ..][0..4], @as(u32, @intCast(value)), .little), + => std.mem.writeInt(u32, atom.code.items[reloc.offset - atom.original_offset ..][0..4], @as(u32, @truncate(value)), .little), .R_WASM_TABLE_INDEX_I64, .R_WASM_MEMORY_ADDR_I64, => 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 { .R_WASM_TABLE_NUMBER_LEB, .R_WASM_TYPE_INDEX_LEB, .R_WASM_MEMORY_ADDR_TLS_SLEB, - => leb.writeUnsignedFixed(5, atom.code.items[reloc.offset - atom.original_offset ..][0..5], @as(u32, @intCast(value))), + => leb.writeUnsignedFixed(5, atom.code.items[reloc.offset - atom.original_offset ..][0..5], @as(u32, @truncate(value))), .R_WASM_MEMORY_ADDR_LEB64, .R_WASM_MEMORY_ADDR_SLEB64, .R_WASM_TABLE_INDEX_SLEB64, @@ -140,6 +140,13 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 { const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin); const symbol = target_loc.getSymbol(wasm_bin); + if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and + symbol.tag != .section and + symbol.isDead()) + { + const val = atom.thombstone(wasm_bin) orelse relocation.addend; + return @bitCast(val); + } switch (relocation.relocation_type) { .R_WASM_FUNCTION_INDEX_LEB => return symbol.index, .R_WASM_TABLE_NUMBER_LEB => return symbol.index, @@ -170,30 +177,43 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa if (symbol.isUndefined()) { return 0; } - const va = @as(i64, @intCast(symbol.virtual_address)); + const va: i33 = @intCast(symbol.virtual_address); return @intCast(va + relocation.addend); }, .R_WASM_EVENT_INDEX_LEB => return symbol.index, .R_WASM_SECTION_OFFSET_I32 => { const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?; const target_atom = wasm_bin.getAtom(target_atom_index); - const rel_value: i32 = @intCast(target_atom.offset); + const rel_value: i33 = @intCast(target_atom.offset); return @intCast(rel_value + relocation.addend); }, .R_WASM_FUNCTION_OFFSET_I32 => { - const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse { - return @as(u32, @bitCast(@as(i32, -1))); - }; + if (symbol.isUndefined()) { + const val = atom.thombstone(wasm_bin) orelse relocation.addend; + return @bitCast(val); + } + const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?; const target_atom = wasm_bin.getAtom(target_atom_index); - const offset: u32 = 11 + Wasm.getULEB128Size(target_atom.size); // Header (11 bytes fixed-size) + body size (leb-encoded) - const rel_value: i32 = @intCast(target_atom.offset + offset); + const rel_value: i33 = @intCast(target_atom.offset); return @intCast(rel_value + relocation.addend); }, .R_WASM_MEMORY_ADDR_TLS_SLEB, .R_WASM_MEMORY_ADDR_TLS_SLEB64, => { - const va: i32 = @intCast(symbol.virtual_address); + const va: i33 = @intCast(symbol.virtual_address); return @intCast(va + relocation.addend); }, } } + +// For a given `Atom` returns whether it has a thombstone value or not. +/// This defines whether we want a specific value when a section is dead. +fn thombstone(atom: Atom, wasm: *const Wasm) ?i64 { + const atom_name = atom.symbolLoc().getName(wasm); + if (std.mem.eql(u8, atom_name, ".debug_ranges") or std.mem.eql(u8, atom_name, ".debug_loc")) { + return -2; + } else if (std.mem.startsWith(u8, atom_name, ".debug_")) { + return -1; + } + return null; +}