[lld] 182b72a - [lld][WebAssembly] Generate TLS relocation code also when linking statically

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 29 13:26:42 PDT 2021


Author: Sam Clegg
Date: 2021-10-29T13:26:35-07:00
New Revision: 182b72aa486f618907c2bb7581a9d123738767eb

URL: https://github.com/llvm/llvm-project/commit/182b72aa486f618907c2bb7581a9d123738767eb
DIFF: https://github.com/llvm/llvm-project/commit/182b72aa486f618907c2bb7581a9d123738767eb.diff

LOG: [lld][WebAssembly] Generate TLS relocation code also when linking statically

Previously relocations were only generated for PIC output, but
relocations for TLS GOT entries are always needed when shared
memory is enabled, not just in PIC mode.

This means that the `__wasm_apply_global_tls_relocs` is now
generated even for statically linked (non-PIC) output.  Without
this the globals that hold the addresses of TLS symbols are
not set correctly.

Differential Revision: https://reviews.llvm.org/D112833

Added: 
    

Modified: 
    lld/test/wasm/pie.ll
    lld/test/wasm/tls-non-shared-memory.s
    lld/test/wasm/tls.s
    lld/wasm/SyntheticSections.cpp
    lld/wasm/SyntheticSections.h
    lld/wasm/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll
index 0dba0aab02d6f..ee2f02777fda9 100644
--- a/lld/test/wasm/pie.ll
+++ b/lld/test/wasm/pie.ll
@@ -91,7 +91,7 @@ declare void @external_func()
 ; 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 @@ declare void @external_func()
 ; 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
index 222db777df29c..0468129bab5b1 100644
--- a/lld/test/wasm/tls-non-shared-memory.s
+++ b/lld/test/wasm/tls-non-shared-memory.s
@@ -48,6 +48,9 @@ tls1:
 # 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
index 4544c74756325..a8345a367caa8 100644
--- a/lld/test/wasm/tls.s
+++ b/lld/test/wasm/tls.s
@@ -33,6 +33,17 @@ tls_align:
   global.get __tls_align
   end_function
 
+# TLS symbols can also be accessed by `global.get tls1 at 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 at GOT@TLS
+  end_function
+
 .section  .bss.no_tls,"",@
 .globl  no_tls
 .p2align  2
@@ -114,7 +125,7 @@ tls3:
 # 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 @@ tls3:
 # 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:      <tls1_addr>:
+# 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: <tls1_addr>:
 # ASM-EMPTY:
 # ASM-NEXT:   global.get 1
 # ASM-NEXT:   i32.const 0
 # ASM-NEXT:   i32.add
 # ASM-NEXT:   end
 
-# ASM:      <tls2_addr>:
+# ASM-LABEL: <tls2_addr>:
 # ASM-EMPTY:
 # ASM-NEXT:   global.get 1
 # ASM-NEXT:   i32.const 4
 # ASM-NEXT:   i32.add
 # ASM-NEXT:   end
 
-# ASM:      <tls3_addr>:
+# ASM-LABEL: <tls3_addr>:
 # ASM-EMPTY:
 # ASM-NEXT:   global.get 1
 # ASM-NEXT:   i32.const 8
 # ASM-NEXT:   i32.add
 # ASM-NEXT:   end
 
-# ASM:      <tls_align>:
+# ASM-LABEL: <tls_align>:
 # 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 @@ tls3:
 # 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.cpp b/lld/wasm/SyntheticSections.cpp
index 37b498a2ed8e4..7fc5c32402d3d 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -455,10 +455,18 @@ void GlobalSection::writeBody() {
   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<DefinedData>(sym))

diff  --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h
index 4caab9d4a3c7f..956c896148db0 100644
--- a/lld/wasm/SyntheticSections.h
+++ b/lld/wasm/SyntheticSections.h
@@ -287,7 +287,16 @@ class GlobalSection : public SyntheticSection {
   // 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<DefinedData *> dataAddressGlobals;

diff  --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index d504593a7dd78..91e90ae5103a3 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -997,6 +997,14 @@ void Writer::createSyntheticInitFunctions() {
     WasmSym::initMemory->markLive();
   }
 
+  if (config->sharedMemory && out.globalSec->needsTLSRelocations()) {
+    WasmSym::applyGlobalTLSRelocs = symtab->addSyntheticFunction(
+        "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
+        make<SyntheticFunction>(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 @@ void Writer::createSyntheticInitFunctions() {
           "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
           make<SyntheticFunction>(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<SyntheticFunction>(nullSignature,
-                                    "__wasm_apply_global_tls_relocs"));
-        WasmSym::applyGlobalTLSRelocs->markLive();
-      }
     }
   }
 


        


More information about the llvm-commits mailing list