mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 01:16: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
|
||||
|
||||
; 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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -33,6 +33,17 @@ tls_align:
|
||||
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 @@ 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
|
||||
|
@ -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))
|
||||
|
@ -287,7 +287,16 @@ public:
|
||||
// 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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user