[llvm] [WebAssembly] Allow absolute symbols in the linking section (symbol table) (PR #67493)
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 26 14:44:14 PDT 2023
https://github.com/sbc100 created https://github.com/llvm/llvm-project/pull/67493
Fixes a crash in `-Wl,-emit-relocs` where the linker was not able to write linker-synthetic absolute symbols to the symbol table.
This change adds a new symbol flag (`WASM_SYMBOL_ABS`), which means that the symbol's offset is absolute and not relative to a given segment. Such symbols include `__stack_low` and `__stack_low`.
Note that wasm object files never contains such symbols, only binaries linked with `-Wl,-emit-relocs`.
Fixes: #67111
>From ea09121324b22cf1897da33324209159f9c39826 Mon Sep 17 00:00:00 2001
From: Sam Clegg <sbc at chromium.org>
Date: Tue, 26 Sep 2023 14:37:15 -0700
Subject: [PATCH] [WebAssembly] Allow absolute symbols in the linking section
(symbol table)
Fixes a crash in `-Wl,-emit-relocs` where the linker was not able to
write linker-synthetic absolute symbols to the symbol table.
This change adds a new symbol flag (`WASM_SYMBOL_ABS`), which means that
the symbol's offset is absolute and not relative to a given segment.
Such symbols include `__stack_low` and `__stack_low`.
Note that wasm object files never contains such symbols, only binaries
linked with `-Wl,-emit-relocs`.
Fixes: #67111
---
lld/wasm/SymbolTable.cpp | 6 ++++--
lld/wasm/SyntheticSections.cpp | 11 ++++++++---
llvm/include/llvm/BinaryFormat/Wasm.h | 1 +
llvm/lib/Object/WasmObjectFile.cpp | 21 ++++++++++++---------
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 9a381e95f3d9fa5..12e593577d63bd4 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -233,7 +233,8 @@ DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name,
else if (!s || s->isDefined())
return nullptr;
LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n");
- auto *rtn = replaceSymbol<DefinedData>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN);
+ auto *rtn = replaceSymbol<DefinedData>(
+ s, name, WASM_SYMBOL_VISIBILITY_HIDDEN | WASM_SYMBOL_ABS);
rtn->setVA(value);
rtn->referenced = true;
return rtn;
@@ -243,7 +244,8 @@ DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name,
uint32_t flags) {
LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n");
assert(!find(name));
- return replaceSymbol<DefinedData>(insertName(name).first, name, flags);
+ return replaceSymbol<DefinedData>(insertName(name).first, name,
+ flags | WASM_SYMBOL_ABS);
}
DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags,
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index ef9547593acdcd0..3a9c147161a2d38 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -665,9 +665,14 @@ void LinkingSection::writeBody() {
} else if (isa<DataSymbol>(sym)) {
writeStr(sub.os, sym->getName(), "sym name");
if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
- writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
- writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
- "data offset");
+ if (dataSym->segment) {
+ writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
+ writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
+ "data offset");
+ } else {
+ writeUleb128(sub.os, 0, "index");
+ writeUleb128(sub.os, dataSym->getVA(), "data offset");
+ }
writeUleb128(sub.os, dataSym->getSize(), "data size");
}
} else {
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 749d43b840d5c2c..69b286607cbd3a7 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -412,6 +412,7 @@ const unsigned WASM_SYMBOL_EXPORTED = 0x20;
const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
const unsigned WASM_SYMBOL_NO_STRIP = 0x80;
const unsigned WASM_SYMBOL_TLS = 0x100;
+const unsigned WASM_SYMBOL_ABS = 0x200;
#define WASM_RELOC(name, value) name = value,
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index e9471adf66eda5d..50ef4d2648ece73 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -723,17 +723,20 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Info.Name = readString(Ctx);
if (IsDefined) {
auto Index = readVaruint32(Ctx);
- if (Index >= DataSegments.size())
- return make_error<GenericBinaryError>("invalid data segment index",
- object_error::parse_failed);
auto Offset = readVaruint64(Ctx);
auto Size = readVaruint64(Ctx);
- size_t SegmentSize = DataSegments[Index].Data.Content.size();
- if (Offset > SegmentSize)
- return make_error<GenericBinaryError>(
- "invalid data symbol offset: `" + Info.Name + "` (offset: " +
- Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
- object_error::parse_failed);
+ if (!(Info.Flags & wasm::WASM_SYMBOL_ABS)) {
+ if (static_cast<size_t>(Index) >= DataSegments.size())
+ return make_error<GenericBinaryError>(
+ "invalid data segment index: " + Twine(Index),
+ object_error::parse_failed);
+ size_t SegmentSize = DataSegments[Index].Data.Content.size();
+ if (Offset > SegmentSize)
+ return make_error<GenericBinaryError>(
+ "invalid data symbol offset: `" + Info.Name + "` (offset: " +
+ Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
+ object_error::parse_failed);
+ }
Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
}
break;
More information about the llvm-commits
mailing list