mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 10:26:06 +00:00
[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
This commit is contained in:
parent
fe953b15cf
commit
182b72aa48
@ -91,7 +91,7 @@ declare void @external_func()
|
|||||||
; RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM
|
; RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM
|
||||||
|
|
||||||
; SHMEM: - Type: CODE
|
; SHMEM: - Type: CODE
|
||||||
; SHMEM: - Index: 7
|
; SHMEM: - Index: 6
|
||||||
; SHMEM-NEXT: Locals: []
|
; SHMEM-NEXT: Locals: []
|
||||||
; SHMEM-NEXT: Body: 100310050B
|
; SHMEM-NEXT: Body: 100310050B
|
||||||
|
|
||||||
@ -109,13 +109,11 @@ declare void @external_func()
|
|||||||
; SHMEM-NEXT: - Index: 5
|
; SHMEM-NEXT: - Index: 5
|
||||||
; SHMEM-NEXT: Name: __wasm_apply_global_relocs
|
; SHMEM-NEXT: Name: __wasm_apply_global_relocs
|
||||||
; SHMEM-NEXT: - Index: 6
|
; SHMEM-NEXT: - Index: 6
|
||||||
; SHMEM-NEXT: Name: __wasm_apply_global_tls_relocs
|
|
||||||
; SHMEM-NEXT: - Index: 7
|
|
||||||
; SHMEM-NEXT: Name: __wasm_start
|
; SHMEM-NEXT: Name: __wasm_start
|
||||||
; SHMEM-NEXT: - Index: 8
|
; SHMEM-NEXT: - Index: 7
|
||||||
; SHMEM-NEXT: Name: foo
|
; SHMEM-NEXT: Name: foo
|
||||||
; SHMEM-NEXT: - Index: 9
|
; SHMEM-NEXT: - Index: 8
|
||||||
; SHMEM-NEXT: Name: get_data_address
|
; SHMEM-NEXT: Name: get_data_address
|
||||||
; SHMEM-NEXT: - Index: 10
|
; SHMEM-NEXT: - Index: 9
|
||||||
; SHMEM-NEXT: Name: _start
|
; SHMEM-NEXT: Name: _start
|
||||||
|
|
||||||
|
@ -48,6 +48,9 @@ tls1:
|
|||||||
# RUN: wasm-ld --experimental-pic -shared -o %t.so %t.o
|
# RUN: wasm-ld --experimental-pic -shared -o %t.so %t.o
|
||||||
# RUN: obj2yaml %t.so | FileCheck %s --check-prefix=PIC
|
# 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
|
# CHECK: - Type: GLOBAL
|
||||||
# __stack_pointer
|
# __stack_pointer
|
||||||
# CHECK-NEXT: Globals:
|
# CHECK-NEXT: Globals:
|
||||||
|
@ -33,6 +33,17 @@ tls_align:
|
|||||||
global.get __tls_align
|
global.get __tls_align
|
||||||
end_function
|
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,"",@
|
.section .bss.no_tls,"",@
|
||||||
.globl no_tls
|
.globl no_tls
|
||||||
.p2align 2
|
.p2align 2
|
||||||
@ -114,7 +125,7 @@ tls3:
|
|||||||
# CHECK-NEXT: Value: 4
|
# CHECK-NEXT: Value: 4
|
||||||
|
|
||||||
|
|
||||||
# ASM: <__wasm_init_tls>:
|
# ASM-LABEL: <__wasm_init_tls>:
|
||||||
# ASM-EMPTY:
|
# ASM-EMPTY:
|
||||||
# ASM-NEXT: local.get 0
|
# ASM-NEXT: local.get 0
|
||||||
# ASM-NEXT: global.set 1
|
# ASM-NEXT: global.set 1
|
||||||
@ -122,33 +133,43 @@ tls3:
|
|||||||
# ASM-NEXT: i32.const 0
|
# ASM-NEXT: i32.const 0
|
||||||
# ASM-NEXT: i32.const 12
|
# ASM-NEXT: i32.const 12
|
||||||
# ASM-NEXT: memory.init 0, 0
|
# ASM-NEXT: memory.init 0, 0
|
||||||
|
# call to __wasm_apply_global_tls_relocs>
|
||||||
|
# ASM-NEXT: call 3
|
||||||
# ASM-NEXT: end
|
# 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-EMPTY:
|
||||||
# ASM-NEXT: global.get 1
|
# ASM-NEXT: global.get 1
|
||||||
# ASM-NEXT: i32.const 0
|
# ASM-NEXT: i32.const 0
|
||||||
# ASM-NEXT: i32.add
|
# ASM-NEXT: i32.add
|
||||||
# ASM-NEXT: end
|
# ASM-NEXT: end
|
||||||
|
|
||||||
# ASM: <tls2_addr>:
|
# ASM-LABEL: <tls2_addr>:
|
||||||
# ASM-EMPTY:
|
# ASM-EMPTY:
|
||||||
# ASM-NEXT: global.get 1
|
# ASM-NEXT: global.get 1
|
||||||
# ASM-NEXT: i32.const 4
|
# ASM-NEXT: i32.const 4
|
||||||
# ASM-NEXT: i32.add
|
# ASM-NEXT: i32.add
|
||||||
# ASM-NEXT: end
|
# ASM-NEXT: end
|
||||||
|
|
||||||
# ASM: <tls3_addr>:
|
# ASM-LABEL: <tls3_addr>:
|
||||||
# ASM-EMPTY:
|
# ASM-EMPTY:
|
||||||
# ASM-NEXT: global.get 1
|
# ASM-NEXT: global.get 1
|
||||||
# ASM-NEXT: i32.const 8
|
# ASM-NEXT: i32.const 8
|
||||||
# ASM-NEXT: i32.add
|
# ASM-NEXT: i32.add
|
||||||
# ASM-NEXT: end
|
# ASM-NEXT: end
|
||||||
|
|
||||||
# ASM: <tls_align>:
|
# ASM-LABEL: <tls_align>:
|
||||||
# ASM-EMPTY:
|
# ASM-EMPTY:
|
||||||
# ASM-NEXT: global.get 3
|
# ASM-NEXT: global.get 3
|
||||||
# ASM-NEXT: end
|
# ASM-NEXT: end
|
||||||
|
|
||||||
# Also verify TLS usage with --relocatable
|
# Also verify TLS usage with --relocatable
|
||||||
# RUN: wasm-ld --relocatable -o %t3.wasm %t.o
|
# RUN: wasm-ld --relocatable -o %t3.wasm %t.o
|
||||||
@ -172,6 +193,8 @@ tls3:
|
|||||||
# RELOC-NEXT: Name: __tls_base
|
# RELOC-NEXT: Name: __tls_base
|
||||||
# RELOC-NEXT: - Index: 1
|
# RELOC-NEXT: - Index: 1
|
||||||
# RELOC-NEXT: Name: __tls_align
|
# RELOC-NEXT: Name: __tls_align
|
||||||
|
# RELOC-NEXT: - Index: 2
|
||||||
|
# RELOC-NEXT: Name: GOT.data.internal.tls1
|
||||||
# RELOC-NEXT: DataSegmentNames:
|
# RELOC-NEXT: DataSegmentNames:
|
||||||
# RELOC-NEXT: - Index: 0
|
# RELOC-NEXT: - Index: 0
|
||||||
# RELOC-NEXT: Name: .tdata
|
# RELOC-NEXT: Name: .tdata
|
||||||
|
@ -455,10 +455,18 @@ void GlobalSection::writeBody() {
|
|||||||
bool is64 = config->is64.getValueOr(false);
|
bool is64 = config->is64.getValueOr(false);
|
||||||
uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
|
uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
|
||||||
for (const Symbol *sym : internalGotSymbols) {
|
for (const Symbol *sym : internalGotSymbols) {
|
||||||
// In the case of dynamic linking, internal GOT entries
|
bool mutable_ = false;
|
||||||
// need to be mutable since they get updated to the correct
|
if (!sym->isStub) {
|
||||||
// runtime value during `__wasm_apply_global_relocs`.
|
// In the case of dynamic linking, these global must to be mutable since
|
||||||
bool mutable_ = config->isPic & !sym->isStub;
|
// 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_};
|
WasmGlobalType type{itype, mutable_};
|
||||||
WasmInitExpr initExpr;
|
WasmInitExpr initExpr;
|
||||||
if (auto *d = dyn_cast<DefinedData>(sym))
|
if (auto *d = dyn_cast<DefinedData>(sym))
|
||||||
|
@ -287,7 +287,16 @@ public:
|
|||||||
// specific relocation types combined with linker relaxation which could
|
// specific relocation types combined with linker relaxation which could
|
||||||
// transform a `global.get` to an `i32.const`.
|
// transform a `global.get` to an `i32.const`.
|
||||||
void addInternalGOTEntry(Symbol *sym);
|
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;
|
void generateRelocationCode(raw_ostream &os, bool TLS) const;
|
||||||
|
|
||||||
std::vector<DefinedData *> dataAddressGlobals;
|
std::vector<DefinedData *> dataAddressGlobals;
|
||||||
|
@ -997,6 +997,14 @@ void Writer::createSyntheticInitFunctions() {
|
|||||||
WasmSym::initMemory->markLive();
|
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) {
|
if (config->isPic) {
|
||||||
// For PIC code we create synthetic functions that apply relocations.
|
// For PIC code we create synthetic functions that apply relocations.
|
||||||
// These get called from __wasm_call_ctors before the user-level
|
// 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,
|
"__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
|
||||||
make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
|
make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
|
||||||
WasmSym::applyGlobalRelocs->markLive();
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user