[lld] bda8b84 - [lld][WebAssembly] Disallow exporting of TLS symbols
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Mon May 10 10:05:42 PDT 2021
Author: Sam Clegg
Date: 2021-05-10T09:58:44-07:00
New Revision: bda8b8488442215e0557a53016a8d9c0a36b90c5
URL: https://github.com/llvm/llvm-project/commit/bda8b8488442215e0557a53016a8d9c0a36b90c5
DIFF: https://github.com/llvm/llvm-project/commit/bda8b8488442215e0557a53016a8d9c0a36b90c5.diff
LOG: [lld][WebAssembly] Disallow exporting of TLS symbols
Cross module TLS is currently not supported by our ABI. This
change makes explicitly exporting a TLS symbol into an error
and prevents implicit exporting (via --export-all).
See https://github.com/emscripten-core/emscripten/issues/14120
Differential Revision: https://reviews.llvm.org/D102044
Added:
lld/test/wasm/tls-export.s
Modified:
lld/wasm/InputChunks.h
lld/wasm/InputFiles.cpp
lld/wasm/OutputSegment.h
lld/wasm/Relocations.cpp
lld/wasm/Symbols.cpp
lld/wasm/Symbols.h
lld/wasm/Writer.cpp
Removed:
################################################################################
diff --git a/lld/test/wasm/tls-export.s b/lld/test/wasm/tls-export.s
new file mode 100644
index 0000000000000..b8a36aa55aa1b
--- /dev/null
+++ b/lld/test/wasm/tls-export.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld -no-gc-sections --shared-memory --no-entry -o %t.wasm %t.o
+# RUN: not wasm-ld --shared-memory --no-entry --export=tls1 -o %t.wasm %t.o 2>&1 | FileCheck %s
+# With --export-all we ignore TLS symbols so we don't expect an error here
+# RUN: wasm-ld --shared-memory --no-entry --export-all -o %t.wasm %t.o
+
+# CHECK: error: TLS symbols cannot yet be exported: `tls1`
+
+.section .tdata.tls1,"",@
+.globl tls1
+.p2align 2
+tls1:
+ .int32 1
+ .size tls1, 4
+
+.section .custom_section.target_features,"",@
+ .int8 3
+ .int8 43
+ .int8 7
+ .ascii "atomics"
+ .int8 43
+ .int8 11
+ .ascii "bulk-memory"
+ .int8 43
+ .int8 15
+ .ascii "mutable-globals"
diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h
index fe30fea62d1cc..f17751b312931 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -117,6 +117,9 @@ class InputSegment : public InputChunk {
const OutputSegment *outputSeg = nullptr;
uint32_t outputSegmentOffset = 0;
uint32_t alignment = 0;
+ bool isTLS() {
+ return getName().startswith(".tdata") || getName().startswith(".tbss");
+ }
protected:
ArrayRef<uint8_t> data() const override { return segment.Data.Content; }
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 889280a71c1ad..3b1dccbe46670 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -247,7 +247,7 @@ uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone,
// 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->name == ".tdata")
+ if (D->segment && D->segment->outputSeg->isTLS())
return D->getOutputSegmentOffset() + reloc.Addend;
uint64_t value = D->getVA(reloc.Addend);
diff --git a/lld/wasm/OutputSegment.h b/lld/wasm/OutputSegment.h
index 30553b9883e22..c9d58cf231b80 100644
--- a/lld/wasm/OutputSegment.h
+++ b/lld/wasm/OutputSegment.h
@@ -32,6 +32,8 @@ class OutputSegment {
size += inSeg->getSize();
}
+ bool isTLS() const { return name == ".tdata"; }
+
StringRef name;
bool isBss = false;
uint32_t index = 0;
diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index 18eb522ebe0b7..f909c377b9a54 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -115,7 +115,7 @@ void scanRelocations(InputChunk *chunk) {
break;
case R_WASM_MEMORY_ADDR_TLS_SLEB:
if (auto *D = dyn_cast<DefinedData>(sym)) {
- if (D->segment->outputSeg->name != ".tdata") {
+ if (!D->segment->outputSeg->isTLS()) {
error(toString(file) + ": relocation " +
relocTypeToString(reloc.Type) + " cannot be used against `" +
toString(*sym) +
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index 2bb89ae8ea5fe..66f276ba10fc7 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -207,13 +207,14 @@ bool Symbol::isExported() const {
if (!isDefined() || isLocal())
return false;
- if (forceExport || config->exportAll)
+ if (config->exportAll || (config->exportDynamic && !isHidden()))
return true;
- if (config->exportDynamic && !isHidden())
- return true;
+ return isExportedExplicit();
+}
- return flags & WASM_SYMBOL_EXPORTED;
+bool Symbol::isExportedExplicit() const {
+ return forceExport || flags & WASM_SYMBOL_EXPORTED;
}
bool Symbol::isNoStrip() const {
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index e2a594ff0bef3..e6968d45261a5 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -110,6 +110,7 @@ class Symbol {
WasmSymbolType getWasmType() const;
bool isExported() const;
+ bool isExportedExplicit() const;
// Indicates that the symbol is used in an __attribute__((used)) directive
// or similar.
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index dbe947daf781c..7598d6f360d4a 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -270,7 +270,7 @@ void Writer::layoutMemory() {
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
memoryPtr, seg->size, seg->alignment));
- if (!config->relocatable && seg->name == ".tdata") {
+ if (!config->relocatable && seg->isTLS()) {
if (config->sharedMemory) {
auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
setGlobalPtr(tlsSize, seg->size);
@@ -631,6 +631,12 @@ void Writer::calculateExports() {
} else if (auto *e = dyn_cast<DefinedEvent>(sym)) {
export_ = {name, WASM_EXTERNAL_EVENT, e->getEventIndex()};
} else if (auto *d = dyn_cast<DefinedData>(sym)) {
+ if (d->segment && d->segment->isTLS()) {
+ // We can't currenly export TLS data symbols.
+ if (sym->isExportedExplicit())
+ error("TLS symbols cannot yet be exported: `" + toString(*sym) + "`");
+ continue;
+ }
out.globalSec->dataAddressGlobals.push_back(d);
export_ = {name, WASM_EXTERNAL_GLOBAL, globalIndex++};
} else {
@@ -900,7 +906,7 @@ void Writer::combineOutputSegments() {
OutputSegment *combined = nullptr;
std::vector<OutputSegment *> new_segments;
for (OutputSegment *s : segments) {
- if (s->name == ".tdata") {
+ if (s->isTLS()) {
new_segments.push_back(s);
} else {
if (!combined) {
@@ -946,7 +952,7 @@ static void createFunction(DefinedFunction *func, StringRef bodyContent) {
bool Writer::needsPassiveInitialization(const OutputSegment *segment) {
return segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE &&
- segment->name != ".tdata" && !segment->isBss;
+ !segment->isTLS() && !segment->isBss;
}
bool Writer::hasPassiveInitializedSegments() {
More information about the llvm-commits
mailing list