mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
wasm-linker: implement runtime TLS relocations
This commit is contained in:
parent
9d13c2257d
commit
9fce1df4cd
@ -139,6 +139,8 @@ archives: std.ArrayListUnmanaged(Archive) = .{},
|
||||
|
||||
/// A map of global names (read: offset into string table) to their symbol location
|
||||
globals: std.AutoHashMapUnmanaged(u32, SymbolLoc) = .{},
|
||||
/// The list of GOT symbols and their location
|
||||
got_symbols: std.ArrayListUnmanaged(SymbolLoc) = .{},
|
||||
/// Maps discarded symbols and their positions to the location of the symbol
|
||||
/// it was resolved to
|
||||
discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{},
|
||||
@ -635,6 +637,15 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn requiresTLSReloc(wasm: *const Wasm) bool {
|
||||
for (wasm.got_symbols.items) |loc| {
|
||||
if (loc.getSymbol(wasm).isTLS()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
|
||||
const object: Object = wasm.objects.items[object_index];
|
||||
log.debug("Resolving symbols in object: '{s}'", .{object.name});
|
||||
@ -813,6 +824,48 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn setupTLSRelocationsFunction(wasm: *Wasm) !void {
|
||||
// When we have TLS GOT entries and shared memory is enabled,
|
||||
// we must perform runtime relocations or else we don't create the function.
|
||||
if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// const loc = try wasm.createSyntheticSymbol("__wasm_apply_global_tls_relocs");
|
||||
var function_body = std.ArrayList(u8).init(wasm.base.allocator);
|
||||
defer function_body.deinit();
|
||||
const writer = function_body.writer();
|
||||
|
||||
// locals (we have none)
|
||||
try writer.writeByte(0);
|
||||
for (wasm.got_symbols.items, 0..) |got_loc, got_index| {
|
||||
const sym: *Symbol = got_loc.getSymbol(wasm);
|
||||
if (!sym.isTLS()) continue; // only relocate TLS symbols
|
||||
if (sym.tag == .data and sym.isDefined()) {
|
||||
// get __tls_base
|
||||
try writer.writeByte(std.wasm.opcode(.global_get));
|
||||
try leb.writeULEB128(writer, wasm.findGlobalSymbol("__tls_base").?.getSymbol(wasm).index);
|
||||
|
||||
// add the virtual address of the symbol
|
||||
try writer.writeByte(std.wasm.opcode(.i32_const));
|
||||
try leb.writeULEB128(writer, sym.virtual_address);
|
||||
} else if (sym.tag == .function) {
|
||||
@panic("TODO: relocate GOT entry of function");
|
||||
} else continue;
|
||||
|
||||
try writer.writeByte(std.wasm.opcode(.i32_add));
|
||||
try writer.writeByte(std.wasm.opcode(.global_set));
|
||||
try leb.writeULEB128(writer, wasm.imported_globals_count + @intCast(u32, wasm.wasm_globals.items.len + got_index));
|
||||
}
|
||||
try writer.writeByte(std.wasm.opcode(.end));
|
||||
|
||||
try wasm.createSyntheticFunction(
|
||||
"__wasm_apply_global_tls_relocs",
|
||||
std.wasm.Type{ .params = &.{}, .returns = &.{} },
|
||||
&function_body,
|
||||
);
|
||||
}
|
||||
|
||||
fn validateFeatures(
|
||||
wasm: *const Wasm,
|
||||
to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool,
|
||||
@ -2083,6 +2136,14 @@ fn initializeTLSFunction(wasm: *Wasm) !void {
|
||||
try leb.writeULEB128(writer, @as(u32, 0));
|
||||
}
|
||||
|
||||
// If we have to perform any TLS relocations, call the corresponding function
|
||||
// which performs all runtime TLS relocations. This is a synthetic function,
|
||||
// generated by the linker.
|
||||
if (wasm.findGlobalSymbol("__wasm_apply_global_tls_relocs")) |loc| {
|
||||
try writer.writeByte(std.wasm.opcode(.call));
|
||||
try leb.writeULEB128(writer, loc.getSymbol(wasm).index);
|
||||
}
|
||||
|
||||
try writer.writeByte(std.wasm.opcode(.end));
|
||||
|
||||
try wasm.createSyntheticFunction(
|
||||
@ -2939,6 +3000,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
|
||||
try wasm.mergeSections();
|
||||
try wasm.mergeTypes();
|
||||
try wasm.initializeCallCtorsFunction();
|
||||
try wasm.setupTLSRelocationsFunction();
|
||||
try wasm.initializeTLSFunction();
|
||||
try wasm.setupExports();
|
||||
try wasm.writeToFile(enabled_features, emit_features_count, arena);
|
||||
@ -3059,6 +3121,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try wasm.mergeSections();
|
||||
try wasm.mergeTypes();
|
||||
try wasm.initializeCallCtorsFunction();
|
||||
try wasm.setupTLSRelocationsFunction();
|
||||
try wasm.initializeTLSFunction();
|
||||
try wasm.setupExports();
|
||||
try wasm.writeToFile(enabled_features, emit_features_count, arena);
|
||||
|
||||
@ -930,11 +930,29 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
|
||||
reloc.offset -= relocatable_data.offset;
|
||||
try atom.relocs.append(gpa, reloc);
|
||||
|
||||
if (relocation.isTableIndex()) {
|
||||
try wasm_bin.function_table.put(gpa, .{
|
||||
.file = object_index,
|
||||
.index = relocation.index,
|
||||
}, 0);
|
||||
switch (relocation.relocation_type) {
|
||||
.R_WASM_TABLE_INDEX_I32,
|
||||
.R_WASM_TABLE_INDEX_I64,
|
||||
.R_WASM_TABLE_INDEX_SLEB,
|
||||
.R_WASM_TABLE_INDEX_SLEB64,
|
||||
=> {
|
||||
try wasm_bin.function_table.put(gpa, .{
|
||||
.file = object_index,
|
||||
.index = relocation.index,
|
||||
}, 0);
|
||||
},
|
||||
.R_WASM_GLOBAL_INDEX_I32,
|
||||
.R_WASM_GLOBAL_INDEX_LEB,
|
||||
=> {
|
||||
const sym = object.symtable[relocation.index];
|
||||
if (sym.tag != .global) {
|
||||
try wasm_bin.got_symbols.append(
|
||||
wasm_bin.base.allocator,
|
||||
.{ .file = object_index, .index = relocation.index },
|
||||
);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,18 +71,6 @@ 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