[WebAssembly] Use GeneralDynamic TLS for exception handling builtins.

These global TLS symbols are shared across all shared libraries and
therefor should not be assumed to be local to the current module.

Also add new error in the linker when TLS relocations are used against
undefined symbols.  TLS relocations are offsets into the current modules
tls data segment, and don't make sense for undefined symbols which are
modeled as global imports.

Fixes: https://github.com/emscripten-core/emscripten/issues/13398

Differential Revision: https://reviews.llvm.org/D119630
This commit is contained in:
Sam Clegg 2022-02-11 15:53:28 -08:00
parent 9dcb006165
commit 37f422f4ac
5 changed files with 13 additions and 5 deletions

View file

@ -6,6 +6,8 @@ _start:
.functype _start () -> ()
i32.const foo@TLSREL
i32.const bar@TLSREL
i32.const baz@TLSREL
drop
drop
drop
end_function
@ -24,3 +26,4 @@ bar:
# CHECK: relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against `foo` in non-TLS section: .data
# CHECK: relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against `bar` in non-TLS section: .bss
# CHECK: relocation R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against an undefined symbol `baz`

View file

@ -112,6 +112,11 @@ void scanRelocations(InputChunk *chunk) {
break;
case R_WASM_MEMORY_ADDR_TLS_SLEB:
case R_WASM_MEMORY_ADDR_TLS_SLEB64:
if (!sym->isDefined()) {
error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +
" cannot be used against an undefined symbol `" + toString(*sym) +
"`");
}
// In single-threaded builds TLS is lowered away and TLS data can be
// merged with normal data and allowing TLS relocation in non-TLS
// segments.

View file

@ -422,7 +422,7 @@ static GlobalVariable *getGlobalVariable(Module &M, Type *Ty,
// shared-memory module, which we don't want to be responsible for.
auto *Subtarget = TM.getSubtargetImpl();
auto TLS = Subtarget->hasAtomics() && Subtarget->hasBulkMemory()
? GlobalValue::LocalExecTLSModel
? GlobalValue::GeneralDynamicTLSModel
: GlobalValue::NotThreadLocal;
GV->setThreadLocalMode(TLS);
return GV;

View file

@ -9,8 +9,8 @@ target triple = "wasm32-unknown-unknown"
@_ZTIc = external constant i8*
; NO-TLS-DAG: __THREW__ = external global [[PTR]]
; NO-TLS-DAG: __threwValue = external global i32
; TLS-DAG: __THREW__ = external thread_local(localexec) global [[PTR]]
; TLS-DAG: __threwValue = external thread_local(localexec) global i32
; TLS-DAG: __THREW__ = external thread_local global [[PTR]]
; TLS-DAG: __threwValue = external thread_local global i32
; Test invoke instruction with clauses (try-catch block)
define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {

View file

@ -10,8 +10,8 @@ target triple = "wasm32-unknown-unknown"
@global_var = global i32 0, align 4
; NO-TLS-DAG: __THREW__ = external global [[PTR]]
; NO-TLS-DAG: __threwValue = external global [[PTR]]
; TLS-DAG: __THREW__ = external thread_local(localexec) global i32
; TLS-DAG: __threwValue = external thread_local(localexec) global i32
; TLS-DAG: __THREW__ = external thread_local global i32
; TLS-DAG: __threwValue = external thread_local global i32
@global_longjmp_ptr = global void (%struct.__jmp_buf_tag*, i32)* @longjmp, align 4
; CHECK-DAG: @global_longjmp_ptr = global void (%struct.__jmp_buf_tag*, i32)* bitcast (void ([[PTR]], i32)* @emscripten_longjmp to void (%struct.__jmp_buf_tag*, i32)*)