diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -169,18 +169,12 @@ case R_WASM_MEMORY_ADDR_REL_SLEB64: case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_I64: + case R_WASM_MEMORY_ADDR_TLS_SLEB: + case R_WASM_MEMORY_ADDR_TLS_SLEB64: case R_WASM_MEMORY_ADDR_LOCREL_I32: { if (isa(sym) || sym->isUndefWeak()) return 0; auto D = cast(sym); - // Treat non-TLS relocation against symbols that live in the TLS segment - // like TLS relocations. This behaviour exists to support older object - // files created before we introduced TLS relocations. - // TODO(sbc): Remove this legacy behaviour one day. This will break - // backward compat with old object files built with `-fPIC`. - if (D->segment && D->segment->outputSeg->isTLS()) - return D->getOutputSegmentOffset() + reloc.Addend; - uint64_t value = D->getVA() + reloc.Addend; if (reloc.Type == R_WASM_MEMORY_ADDR_LOCREL_I32) { const auto *segment = cast(chunk); @@ -190,12 +184,6 @@ } return value; } - case R_WASM_MEMORY_ADDR_TLS_SLEB: - case R_WASM_MEMORY_ADDR_TLS_SLEB64: - if (isa(sym) || sym->isUndefWeak()) - return 0; - // TLS relocations are relative to the start of the TLS output segment - return cast(sym)->getOutputSegmentOffset() + reloc.Addend; case R_WASM_TYPE_INDEX_LEB: return typeMap[reloc.Index]; case R_WASM_FUNCTION_INDEX_LEB: diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -305,6 +305,11 @@ uint64_t DefinedData::getVA() const { LLVM_DEBUG(dbgs() << "getVA: " << getName() << "\n"); + // In the shared memory case, TLS symbols are relative to the start of the TLS + // output segment (__tls_base). When building without shared memory, TLS + // symbols absolute, just like non-TLS. + if (isTLS() && config->sharedMemory) + return getOutputSegmentOffset() + value; if (segment) return segment->getVA(value); return value;