mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 07:33:08 +00:00
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.
This commit is contained in:
parent
7fe629a812
commit
3f22bb96f3
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user