diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-04-13 22:10:02 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-04-14 22:53:13 +0200 |
| commit | cf37101108e56412e958a8b597bae84649893b6f (patch) | |
| tree | 29979e1e3e82acba2b6da1893b834a8636993ede /src/link | |
| parent | 321a1642693b74481e12cae8d7be089c6ef45cc1 (diff) | |
| download | zig-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.zig | 27 | ||||
| -rw-r--r-- | src/link/Wasm/Atom.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm/Object.zig | 15 | ||||
| -rw-r--r-- | src/link/Wasm/types.zig | 12 |
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; |
