wasm-linker: Add function table indexes

When linking with an object file, verify if a relocation is a table index relocation.
If that's the case, add the relocation target to the function table.
This commit is contained in:
Luuk de Gram 2022-04-13 22:10:02 +02:00
parent 321a164269
commit cf37101108
4 changed files with 39 additions and 17 deletions

View File

@ -101,8 +101,8 @@ exports: std.ArrayListUnmanaged(types.Export) = .{},
/// When this is non-zero, we must emit a table entry,
/// as well as an 'elements' section.
///
/// Note: Key is symbol index, value represents the index into the table
function_table: std.AutoHashMapUnmanaged(u32, u32) = .{},
/// Note: Key is symbol location, value represents the index into the table
function_table: std.AutoHashMapUnmanaged(SymbolLoc, u32) = .{},
/// All object files and their data which are linked into the final binary
objects: std.ArrayListUnmanaged(Object) = .{},
@ -363,6 +363,9 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
.index = sym_index,
};
const sym_name = object.string_table.get(symbol.name);
if (mem.eql(u8, sym_name, "__indirect_function_table")) {
continue;
}
const sym_name_index = try self.string_table.put(self.base.allocator, sym_name);
if (symbol.isLocal()) {
@ -837,7 +840,7 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
/// Appends a new entry to the indirect function table
pub fn addTableFunction(self: *Wasm, symbol_index: u32) !void {
const index = @intCast(u32, self.function_table.count());
try self.function_table.put(self.base.allocator, symbol_index, index);
try self.function_table.put(self.base.allocator, .{ .file = null, .index = symbol_index }, index);
}
/// Assigns indexes to all indirect functions.
@ -1017,6 +1020,9 @@ fn setupImports(self: *Wasm) !void {
}
const symbol = symbol_loc.getSymbol(self);
if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) {
continue;
}
if (symbol.tag == .data or !symbol.requiresImport()) {
continue;
}
@ -1166,13 +1172,20 @@ fn setupExports(self: *Wasm) !void {
if (!symbol.isExported()) continue;
const sym_name = sym_loc.getName(self);
const export_name = if (self.export_names.get(sym_loc)) |name| name else symbol.name;
const export_name = if (self.export_names.get(sym_loc)) |name| name else blk: {
if (sym_loc.file == null) break :blk symbol.name;
break :blk try self.string_table.put(self.base.allocator, sym_name);
};
const exp: types.Export = .{
.name = export_name,
.kind = symbol.tag.externalType(),
.index = symbol.index,
};
log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{ sym_name, self.string_table.get(exp.name), exp.index });
log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{
sym_name,
self.string_table.get(exp.name),
exp.index,
});
try self.exports.append(self.base.allocator, exp);
}
@ -1767,8 +1780,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
try leb.writeULEB128(writer, @as(u8, 0));
try leb.writeULEB128(writer, @intCast(u32, self.function_table.count()));
var symbol_it = self.function_table.keyIterator();
while (symbol_it.next()) |symbol_index_ptr| {
try leb.writeULEB128(writer, self.symbols.items[symbol_index_ptr.*].index);
while (symbol_it.next()) |symbol_loc_ptr| {
try leb.writeULEB128(writer, symbol_loc_ptr.*.getSymbol(self).index);
}
try writeVecSectionHeader(

View File

@ -158,7 +158,7 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
.R_WASM_TABLE_INDEX_I64,
.R_WASM_TABLE_INDEX_SLEB,
.R_WASM_TABLE_INDEX_SLEB64,
=> return wasm_bin.function_table.get(relocation.index) orelse 0,
=> return wasm_bin.function_table.get(target_loc) orelse 0,
.R_WASM_TYPE_INDEX_LEB => return wasm_bin.functions.items[symbol.index].type_index,
.R_WASM_GLOBAL_INDEX_I32,
.R_WASM_GLOBAL_INDEX_LEB,

View File

@ -851,15 +851,12 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
reloc.offset -= relocatable_data.offset;
try atom.relocs.append(gpa, reloc);
// TODO: Automatically append the target symbol to the indirect
// function table when the relocation is a table index.
//
// if (relocation.isTableIndex()) {
// try wasm_bin.elements.appendSymbol(gpa, .{
// .file = object_index,
// .sym_index = relocation.index,
// });
// }
if (relocation.isTableIndex()) {
try wasm_bin.function_table.putNoClobber(gpa, .{
.file = object_index,
.index = relocation.index,
}, 0);
}
}
}

View File

@ -67,6 +67,18 @@ pub const Relocation = struct {
};
}
/// Returns true when the relocation represents a table index relocatable
pub fn isTableIndex(self: Relocation) bool {
return switch (self.relocation_type) {
.R_WASM_TABLE_INDEX_I32,
.R_WASM_TABLE_INDEX_I64,
.R_WASM_TABLE_INDEX_SLEB,
.R_WASM_TABLE_INDEX_SLEB64,
=> true,
else => false,
};
}
pub fn format(self: Relocation, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
_ = fmt;
_ = options;