| ... | ... | @@ -139,6 +139,8 @@ archives: std.ArrayListUnmanaged(Archive) = .{}, |
| 139 | 139 | |
| 140 | 140 | /// A map of global names (read: offset into string table) to their symbol location |
| 141 | 141 | globals: std.AutoHashMapUnmanaged(u32, SymbolLoc) = .{}, |
| 142 | /// The list of GOT symbols and their location |
| 143 | got_symbols: std.ArrayListUnmanaged(SymbolLoc) = .{}, |
| 142 | 144 | /// Maps discarded symbols and their positions to the location of the symbol |
| 143 | 145 | /// it was resolved to |
| 144 | 146 | discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{}, |
| ... | ... | @@ -635,6 +637,15 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { |
| 635 | 637 | return true; |
| 636 | 638 | } |
| 637 | 639 | |
| 640 | fn requiresTLSReloc(wasm: *const Wasm) bool { |
| 641 | for (wasm.got_symbols.items) |loc| { |
| 642 | if (loc.getSymbol(wasm).isTLS()) { |
| 643 | return true; |
| 644 | } |
| 645 | } |
| 646 | return false; |
| 647 | } |
| 648 | |
| 638 | 649 | fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { |
| 639 | 650 | const object: Object = wasm.objects.items[object_index]; |
| 640 | 651 | log.debug("Resolving symbols in object: '{s}'", .{object.name}); |
| ... | ... | @@ -813,6 +824,48 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void { |
| 813 | 824 | } |
| 814 | 825 | } |
| 815 | 826 | |
| 827 | fn setupTLSRelocationsFunction(wasm: *Wasm) !void { |
| 828 | // When we have TLS GOT entries and shared memory is enabled, |
| 829 | // we must perform runtime relocations or else we don't create the function. |
| 830 | if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) { |
| 831 | return; |
| 832 | } |
| 833 | |
| 834 | // const loc = try wasm.createSyntheticSymbol("__wasm_apply_global_tls_relocs"); |
| 835 | var function_body = std.ArrayList(u8).init(wasm.base.allocator); |
| 836 | defer function_body.deinit(); |
| 837 | const writer = function_body.writer(); |
| 838 | |
| 839 | // locals (we have none) |
| 840 | try writer.writeByte(0); |
| 841 | for (wasm.got_symbols.items, 0..) |got_loc, got_index| { |
| 842 | const sym: *Symbol = got_loc.getSymbol(wasm); |
| 843 | if (!sym.isTLS()) continue; // only relocate TLS symbols |
| 844 | if (sym.tag == .data and sym.isDefined()) { |
| 845 | // get __tls_base |
| 846 | try writer.writeByte(std.wasm.opcode(.global_get)); |
| 847 | try leb.writeULEB128(writer, wasm.findGlobalSymbol("__tls_base").?.getSymbol(wasm).index); |
| 848 | |
| 849 | // add the virtual address of the symbol |
| 850 | try writer.writeByte(std.wasm.opcode(.i32_const)); |
| 851 | try leb.writeULEB128(writer, sym.virtual_address); |
| 852 | } else if (sym.tag == .function) { |
| 853 | @panic("TODO: relocate GOT entry of function"); |
| 854 | } else continue; |
| 855 | |
| 856 | try writer.writeByte(std.wasm.opcode(.i32_add)); |
| 857 | try writer.writeByte(std.wasm.opcode(.global_set)); |
| 858 | try leb.writeULEB128(writer, wasm.imported_globals_count + @intCast(u32, wasm.wasm_globals.items.len + got_index)); |
| 859 | } |
| 860 | try writer.writeByte(std.wasm.opcode(.end)); |
| 861 | |
| 862 | try wasm.createSyntheticFunction( |
| 863 | "__wasm_apply_global_tls_relocs", |
| 864 | std.wasm.Type{ .params = &.{}, .returns = &.{} }, |
| 865 | &function_body, |
| 866 | ); |
| 867 | } |
| 868 | |
| 816 | 869 | fn validateFeatures( |
| 817 | 870 | wasm: *const Wasm, |
| 818 | 871 | to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool, |
| ... | ... | @@ -2083,6 +2136,14 @@ fn initializeTLSFunction(wasm: *Wasm) !void { |
| 2083 | 2136 | try leb.writeULEB128(writer, @as(u32, 0)); |
| 2084 | 2137 | } |
| 2085 | 2138 | |
| 2139 | // If we have to perform any TLS relocations, call the corresponding function |
| 2140 | // which performs all runtime TLS relocations. This is a synthetic function, |
| 2141 | // generated by the linker. |
| 2142 | if (wasm.findGlobalSymbol("__wasm_apply_global_tls_relocs")) |loc| { |
| 2143 | try writer.writeByte(std.wasm.opcode(.call)); |
| 2144 | try leb.writeULEB128(writer, loc.getSymbol(wasm).index); |
| 2145 | } |
| 2146 | |
| 2086 | 2147 | try writer.writeByte(std.wasm.opcode(.end)); |
| 2087 | 2148 | |
| 2088 | 2149 | try wasm.createSyntheticFunction( |
| ... | ... | @@ -2939,6 +3000,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2939 | 3000 | try wasm.mergeSections(); |
| 2940 | 3001 | try wasm.mergeTypes(); |
| 2941 | 3002 | try wasm.initializeCallCtorsFunction(); |
| 3003 | try wasm.setupTLSRelocationsFunction(); |
| 2942 | 3004 | try wasm.initializeTLSFunction(); |
| 2943 | 3005 | try wasm.setupExports(); |
| 2944 | 3006 | 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 |
| 3059 | 3121 | try wasm.mergeSections(); |
| 3060 | 3122 | try wasm.mergeTypes(); |
| 3061 | 3123 | try wasm.initializeCallCtorsFunction(); |
| 3124 | try wasm.setupTLSRelocationsFunction(); |
| 3062 | 3125 | try wasm.initializeTLSFunction(); |
| 3063 | 3126 | try wasm.setupExports(); |
| 3064 | 3127 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |