aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-04-13 22:10:02 +0200
committerLuuk de Gram <luuk@degram.dev>2022-04-14 22:53:13 +0200
commitcf37101108e56412e958a8b597bae84649893b6f (patch)
tree29979e1e3e82acba2b6da1893b834a8636993ede /src/link
parent321a1642693b74481e12cae8d7be089c6ef45cc1 (diff)
downloadzig-cf37101108e56412e958a8b597bae84649893b6f.tar.gz
zig-cf37101108e56412e958a8b597bae84649893b6f.zip
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.
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Wasm.zig27
-rw-r--r--src/link/Wasm/Atom.zig2
-rw-r--r--src/link/Wasm/Object.zig15
-rw-r--r--src/link/Wasm/types.zig12
4 files changed, 39 insertions, 17 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index ffd3eef7b6..f13e59dc5e 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -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(
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index a3e1c25190..fc45648d9a 100644
--- a/src/link/Wasm/Atom.zig
+++ b/src/link/Wasm/Atom.zig
@@ -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,
diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig
index 471a91e927..1d6dabd9a7 100644
--- a/src/link/Wasm/Object.zig
+++ b/src/link/Wasm/Object.zig
@@ -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);
+ }
}
}
diff --git a/src/link/Wasm/types.zig b/src/link/Wasm/types.zig
index 1dda5cdb5c..2c99f0f003 100644
--- a/src/link/Wasm/types.zig
+++ b/src/link/Wasm/types.zig
@@ -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;