Skip to content

Commit afe957e

Browse files
authored
[WebAssembly] Allow absolute symbols in the linking section (symbol table) (llvm#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: llvm#67111
1 parent be66a2f commit afe957e

File tree

6 files changed

+38
-15
lines changed

6 files changed

+38
-15
lines changed

lld/test/wasm/emit-relocs.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ _start:
1717
drop
1818
i32.const foo
1919
drop
20+
i32.const __stack_low
21+
drop
2022
end_function
2123

2224
.section .bss.data,"",@
@@ -54,3 +56,9 @@ foo:
5456
# CHECK-NEXT: Name: ret32
5557
# CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
5658
# CHECK-NEXT: Function: 1
59+
# CHECK-NEXT: - Index: 2
60+
# CHECK-NEXT: Kind: DATA
61+
# CHECK-NEXT: Name: __stack_low
62+
# CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN, ABSOLUTE ]
63+
# CHECK-NEXT: Offset: 1040
64+
# CHECK-NEXT: Size: 0

lld/wasm/SymbolTable.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,8 @@ DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name,
233233
else if (!s || s->isDefined())
234234
return nullptr;
235235
LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n");
236-
auto *rtn = replaceSymbol<DefinedData>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN);
236+
auto *rtn = replaceSymbol<DefinedData>(
237+
s, name, WASM_SYMBOL_VISIBILITY_HIDDEN | WASM_SYMBOL_ABSOLUTE);
237238
rtn->setVA(value);
238239
rtn->referenced = true;
239240
return rtn;
@@ -243,7 +244,8 @@ DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name,
243244
uint32_t flags) {
244245
LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n");
245246
assert(!find(name));
246-
return replaceSymbol<DefinedData>(insertName(name).first, name, flags);
247+
return replaceSymbol<DefinedData>(insertName(name).first, name,
248+
flags | WASM_SYMBOL_ABSOLUTE);
247249
}
248250

249251
DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags,

lld/wasm/SyntheticSections.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,14 @@ void LinkingSection::writeBody() {
665665
} else if (isa<DataSymbol>(sym)) {
666666
writeStr(sub.os, sym->getName(), "sym name");
667667
if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
668-
writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
669-
writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
670-
"data offset");
668+
if (dataSym->segment) {
669+
writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
670+
writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
671+
"data offset");
672+
} else {
673+
writeUleb128(sub.os, 0, "index");
674+
writeUleb128(sub.os, dataSym->getVA(), "data offset");
675+
}
671676
writeUleb128(sub.os, dataSym->getSize(), "data size");
672677
}
673678
} else {

llvm/include/llvm/BinaryFormat/Wasm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ const unsigned WASM_SYMBOL_EXPORTED = 0x20;
412412
const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
413413
const unsigned WASM_SYMBOL_NO_STRIP = 0x80;
414414
const unsigned WASM_SYMBOL_TLS = 0x100;
415+
const unsigned WASM_SYMBOL_ABSOLUTE = 0x200;
415416

416417
#define WASM_RELOC(name, value) name = value,
417418

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -723,17 +723,21 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
723723
Info.Name = readString(Ctx);
724724
if (IsDefined) {
725725
auto Index = readVaruint32(Ctx);
726-
if (Index >= DataSegments.size())
727-
return make_error<GenericBinaryError>("invalid data segment index",
728-
object_error::parse_failed);
729726
auto Offset = readVaruint64(Ctx);
730727
auto Size = readVaruint64(Ctx);
731-
size_t SegmentSize = DataSegments[Index].Data.Content.size();
732-
if (Offset > SegmentSize)
733-
return make_error<GenericBinaryError>(
734-
"invalid data symbol offset: `" + Info.Name + "` (offset: " +
735-
Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
736-
object_error::parse_failed);
728+
if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
729+
if (static_cast<size_t>(Index) >= DataSegments.size())
730+
return make_error<GenericBinaryError>(
731+
"invalid data segment index: " + Twine(Index),
732+
object_error::parse_failed);
733+
size_t SegmentSize = DataSegments[Index].Data.Content.size();
734+
if (Offset > SegmentSize)
735+
return make_error<GenericBinaryError>(
736+
"invalid data symbol offset: `" + Info.Name +
737+
"` (offset: " + Twine(Offset) +
738+
" segment size: " + Twine(SegmentSize) + ")",
739+
object_error::parse_failed);
740+
}
737741
Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
738742
}
739743
break;

llvm/lib/ObjectYAML/WasmYAML.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,9 @@ void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
518518
IO.mapRequired("Tag", Info.ElementIndex);
519519
} else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) {
520520
if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
521-
IO.mapRequired("Segment", Info.DataRef.Segment);
521+
if ((Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE) == 0) {
522+
IO.mapRequired("Segment", Info.DataRef.Segment);
523+
}
522524
IO.mapOptional("Offset", Info.DataRef.Offset, 0u);
523525
IO.mapRequired("Size", Info.DataRef.Size);
524526
}
@@ -573,6 +575,7 @@ void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset(
573575
BCaseMask(EXPLICIT_NAME, EXPLICIT_NAME);
574576
BCaseMask(NO_STRIP, NO_STRIP);
575577
BCaseMask(TLS, TLS);
578+
BCaseMask(ABSOLUTE, ABSOLUTE);
576579
#undef BCaseMask
577580
}
578581

0 commit comments

Comments
 (0)