mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[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
This commit is contained in:
parent
f44c6f20f5
commit
bda8b84884
26
lld/test/wasm/tls-export.s
Normal file
26
lld/test/wasm/tls-export.s
Normal file
@ -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"
|
@ -117,6 +117,9 @@ public:
|
||||
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; }
|
||||
|
@ -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);
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
size += inSeg->getSize();
|
||||
}
|
||||
|
||||
bool isTLS() const { return name == ".tdata"; }
|
||||
|
||||
StringRef name;
|
||||
bool isBss = false;
|
||||
uint32_t index = 0;
|
||||
|
@ -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) +
|
||||
|
@ -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 {
|
||||
|
@ -110,6 +110,7 @@ public:
|
||||
|
||||
WasmSymbolType getWasmType() const;
|
||||
bool isExported() const;
|
||||
bool isExportedExplicit() const;
|
||||
|
||||
// Indicates that the symbol is used in an __attribute__((used)) directive
|
||||
// or similar.
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user