diff --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll --- a/lld/test/wasm/pie.ll +++ b/lld/test/wasm/pie.ll @@ -91,7 +91,7 @@ ; RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM ; SHMEM: - Type: CODE -; SHMEM: - Index: 7 +; SHMEM: - Index: 6 ; SHMEM-NEXT: Locals: [] ; SHMEM-NEXT: Body: 100310050B @@ -109,13 +109,11 @@ ; SHMEM-NEXT: - Index: 5 ; SHMEM-NEXT: Name: __wasm_apply_global_relocs ; SHMEM-NEXT: - Index: 6 -; SHMEM-NEXT: Name: __wasm_apply_global_tls_relocs -; SHMEM-NEXT: - Index: 7 ; SHMEM-NEXT: Name: __wasm_start -; SHMEM-NEXT: - Index: 8 +; SHMEM-NEXT: - Index: 7 ; SHMEM-NEXT: Name: foo -; SHMEM-NEXT: - Index: 9 +; SHMEM-NEXT: - Index: 8 ; SHMEM-NEXT: Name: get_data_address -; SHMEM-NEXT: - Index: 10 +; SHMEM-NEXT: - Index: 9 ; SHMEM-NEXT: Name: _start diff --git a/lld/test/wasm/tls-non-shared-memory.s b/lld/test/wasm/tls-non-shared-memory.s --- a/lld/test/wasm/tls-non-shared-memory.s +++ b/lld/test/wasm/tls-non-shared-memory.s @@ -48,6 +48,9 @@ # RUN: wasm-ld --experimental-pic -shared -o %t.so %t.o # RUN: obj2yaml %t.so | FileCheck %s --check-prefix=PIC +# RUN: wasm-ld --experimental-pic --no-gc-sections --no-entry -pie -o %t-pie.wasm %t.o +# RUN: obj2yaml %t.so | FileCheck %s --check-prefix=PIC + # CHECK: - Type: GLOBAL # __stack_pointer # CHECK-NEXT: Globals: diff --git a/lld/test/wasm/tls.s b/lld/test/wasm/tls.s --- a/lld/test/wasm/tls.s +++ b/lld/test/wasm/tls.s @@ -33,6 +33,17 @@ global.get __tls_align end_function +# TLS symbols can also be accessed by `global.get tls1@GOT@TLS` +# which is the pattern emitted for non-DSO-local symbols. +# In this case the global that holds that address must be +# initialized by `__wasm_apply_global_tls_relocs` which is +# called by `__wasm_init_tls`. +.globl tls1_got_addr +tls1_got_addr: + .functype tls1_got_addr () -> (i32) + global.get tls1@GOT@TLS + end_function + .section .bss.no_tls,"",@ .globl no_tls .p2align 2 @@ -114,7 +125,7 @@ # CHECK-NEXT: Value: 4 -# ASM: <__wasm_init_tls>: +# ASM-LABEL: <__wasm_init_tls>: # ASM-EMPTY: # ASM-NEXT: local.get 0 # ASM-NEXT: global.set 1 @@ -122,33 +133,43 @@ # ASM-NEXT: i32.const 0 # ASM-NEXT: i32.const 12 # ASM-NEXT: memory.init 0, 0 +# call to __wasm_apply_global_tls_relocs> +# ASM-NEXT: call 3 # ASM-NEXT: end -# ASM: : +# ASM-LABEL: <__wasm_apply_global_tls_relocs>: +# ASM-EMPTY: +# ASM-NEXT: global.get 1 +# ASM-NEXT: i32.const 0 +# ASM-NEXT: i32.add +# ASM-NEXT: global.set 4 +# ASM-NEXT: end + +# ASM-LABEL: : # ASM-EMPTY: # ASM-NEXT: global.get 1 # ASM-NEXT: i32.const 0 # ASM-NEXT: i32.add # ASM-NEXT: end -# ASM: : +# ASM-LABEL: : # ASM-EMPTY: # ASM-NEXT: global.get 1 # ASM-NEXT: i32.const 4 # ASM-NEXT: i32.add # ASM-NEXT: end -# ASM: : +# ASM-LABEL: : # ASM-EMPTY: # ASM-NEXT: global.get 1 # ASM-NEXT: i32.const 8 # ASM-NEXT: i32.add # ASM-NEXT: end -# ASM: : +# ASM-LABEL: : # ASM-EMPTY: -# ASM-NEXT: global.get 3 -# ASM-NEXT: end +# ASM-NEXT: global.get 3 +# ASM-NEXT: end # Also verify TLS usage with --relocatable # RUN: wasm-ld --relocatable -o %t3.wasm %t.o @@ -172,6 +193,8 @@ # RELOC-NEXT: Name: __tls_base # RELOC-NEXT: - Index: 1 # RELOC-NEXT: Name: __tls_align +# RELOC-NEXT: - Index: 2 +# RELOC-NEXT: Name: GOT.data.internal.tls1 # RELOC-NEXT: DataSegmentNames: # RELOC-NEXT: - Index: 0 # RELOC-NEXT: Name: .tdata diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -287,7 +287,16 @@ // specific relocation types combined with linker relaxation which could // transform a `global.get` to an `i32.const`. void addInternalGOTEntry(Symbol *sym); - bool needsRelocations() { return internalGotSymbols.size(); } + bool needsRelocations() { + return llvm::find_if(internalGotSymbols, [=](Symbol *sym) { + return !sym->isTLS(); + }) != internalGotSymbols.end(); + } + bool needsTLSRelocations() { + return llvm::find_if(internalGotSymbols, [=](Symbol *sym) { + return sym->isTLS(); + }) != internalGotSymbols.end(); + } void generateRelocationCode(raw_ostream &os, bool TLS) const; std::vector dataAddressGlobals; diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -455,10 +455,18 @@ bool is64 = config->is64.getValueOr(false); uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32; for (const Symbol *sym : internalGotSymbols) { - // In the case of dynamic linking, internal GOT entries - // need to be mutable since they get updated to the correct - // runtime value during `__wasm_apply_global_relocs`. - bool mutable_ = config->isPic & !sym->isStub; + bool mutable_ = false; + if (!sym->isStub) { + // In the case of dynamic linking, these global must to be mutable since + // they get updated to the correct runtime value during + // `__wasm_apply_global_relocs`. + if (config->isPic && !sym->isTLS()) + mutable_ = true; + // With multi-theadeding any TLS globals must be mutable since they get + // set during `__wasm_apply_global_tls_relocs` + if (config->sharedMemory && sym->isTLS()) + mutable_ = true; + } WasmGlobalType type{itype, mutable_}; WasmInitExpr initExpr; if (auto *d = dyn_cast(sym)) diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -997,6 +997,14 @@ WasmSym::initMemory->markLive(); } + if (config->sharedMemory && out.globalSec->needsTLSRelocations()) { + WasmSym::applyGlobalTLSRelocs = symtab->addSyntheticFunction( + "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN, + make(nullSignature, + "__wasm_apply_global_tls_relocs")); + WasmSym::applyGlobalTLSRelocs->markLive(); + } + if (config->isPic) { // For PIC code we create synthetic functions that apply relocations. // These get called from __wasm_call_ctors before the user-level @@ -1011,13 +1019,6 @@ "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN, make(nullSignature, "__wasm_apply_global_relocs")); WasmSym::applyGlobalRelocs->markLive(); - if (config->sharedMemory) { - WasmSym::applyGlobalTLSRelocs = symtab->addSyntheticFunction( - "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN, - make(nullSignature, - "__wasm_apply_global_tls_relocs")); - WasmSym::applyGlobalTLSRelocs->markLive(); - } } }