mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
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:
parent
321a164269
commit
cf37101108
@ -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(
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user