wasm-linker: Fix relocations for alias'd atoms

When an atom has one or multiple aliasses, we we could not find the
target atom from the alias'd symbol. This is solved by ensuring that
we also insert each alias symbol in the symbol-atom map.
This commit is contained in:
Luuk de Gram 2022-12-18 16:37:00 +01:00
parent 2a62dbda0b
commit dd85092982
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
3 changed files with 36 additions and 14 deletions

View File

@ -1568,9 +1568,13 @@ fn allocateAtoms(wasm: *Wasm) !void {
var atom: *Atom = entry.value_ptr.*.getFirst();
var offset: u32 = 0;
while (true) {
const symbol_loc = atom.symbolLoc();
if (!wasm.resolved_symbols.contains(symbol_loc)) {
atom = atom.next orelse break;
continue;
}
offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment);
atom.offset = offset;
const symbol_loc = atom.symbolLoc();
log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{
symbol_loc.getName(wasm),
offset,
@ -1578,7 +1582,7 @@ fn allocateAtoms(wasm: *Wasm) !void {
atom.size,
});
offset += atom.size;
try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers
try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers
atom = atom.next orelse break;
}
segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);
@ -2579,14 +2583,16 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
// The code section must be sorted in line with the function order.
var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count());
var sorted_atoms = try std.ArrayList(*Atom).initCapacity(gpa, wasm.functions.count());
defer sorted_atoms.deinit();
while (true) {
if (!is_obj) {
atom.resolveRelocs(wasm);
if (wasm.resolved_symbols.contains(atom.symbolLoc())) {
if (!is_obj) {
atom.resolveRelocs(wasm);
}
sorted_atoms.appendAssumeCapacity(atom);
}
sorted_atoms.appendAssumeCapacity(atom);
atom = atom.next orelse break;
}
@ -2641,6 +2647,10 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
// fill in the offset table and the data segments
var current_offset: u32 = 0;
while (true) {
if (!wasm.resolved_symbols.contains(atom.symbolLoc())) {
atom = atom.next orelse break;
continue;
}
if (!is_obj) {
atom.resolveRelocs(wasm);
}
@ -4170,15 +4180,23 @@ fn emitDataRelocations(
try writeCustomSectionHeader(binary_bytes.items, header_offset, size);
}
/// Searches for an a matching function signature, when not found
/// a new entry will be made. The index of the existing/new signature will be returned.
pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 {
pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 {
var index: u32 = 0;
while (index < wasm.func_types.items.len) : (index += 1) {
if (wasm.func_types.items[index].eql(func_type)) return index;
}
return null;
}
/// Searches for an a matching function signature, when not found
/// a new entry will be made. The index of the existing/new signature will be returned.
pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 {
if (wasm.getTypeIndex(func_type)) |index| {
return index;
}
// functype does not exist.
const index = @intCast(u32, wasm.func_types.items.len);
const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);
errdefer wasm.base.allocator.free(params);
const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns);

View File

@ -186,7 +186,11 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
.R_WASM_MEMORY_ADDR_SLEB,
.R_WASM_MEMORY_ADDR_SLEB64,
=> {
std.debug.assert(symbol.tag == .data and !symbol.isUndefined());
std.debug.assert(symbol.tag == .data);
if (symbol.isUndefined()) {
return 0;
}
const merge_segment = wasm_bin.base.options.output_mode != .Obj;
const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
const segment_info = if (target_atom.file) |object_index| blk: {

View File

@ -923,7 +923,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
try atom.relocs.append(gpa, reloc);
if (relocation.isTableIndex()) {
try wasm_bin.function_table.putNoClobber(gpa, .{
try wasm_bin.function_table.put(gpa, .{
.file = object_index,
.index = relocation.index,
}, 0);
@ -938,17 +938,17 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
.index = relocatable_data.getIndex(),
})) |symbols| {
atom.sym_index = symbols.pop();
try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
// symbols referencing the same atom will be added as alias
// or as 'parent' when they are global.
while (symbols.popOrNull()) |idx| {
try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom);
const alias_symbol = object.symtable[idx];
const symbol = object.symtable[atom.sym_index];
if (alias_symbol.isGlobal() and symbol.isLocal()) {
if (alias_symbol.isGlobal()) {
atom.sym_index = idx;
}
}
try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
}
const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];