[lld][WebAssembly] Fix for string merging + negative addends

Don't include the relocation addend when calculating the
virtual address of a symbol.  Instead just pass the symbol's
offset and add the addend afterwards.

Without this fix we hit the `offset is outside the section`
error in MergeInputSegment::getSegmentPiece.

This fixes a real world error we were are seeing in emscripten.

Differential Revision: https://reviews.llvm.org/D102271
This commit is contained in:
Sam Clegg 2021-05-11 08:58:13 -07:00
parent bb726383ac
commit 19cedd3cd3
4 changed files with 17 additions and 6 deletions

View File

@ -1,6 +1,12 @@
// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
// RUN: wasm-ld -O2 %t.o -o %t.wasm --no-gc-sections --no-entry
// RUN: wasm-ld -O1 %t.o -o %t.wasm --no-gc-sections --no-entry
// RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=COMMON,MERGE
// Check that the default is the same as -O1 (since we default to -O1)
// RUN: wasm-ld %t.o -o %t.wasm --no-gc-sections --no-entry
// RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=COMMON,MERGE
// Check that -O0 disables merging
// RUN: wasm-ld -O0 %t.o -o %t2.wasm --no-gc-sections --no-entry
// RUN: obj2yaml %t2.wasm | FileCheck --check-prefixes=COMMON,NOMERGE %s
@ -14,6 +20,11 @@ bar:
.asciz "bc"
.size bar, 4
.section .rodata_relocs,"",@
negative_addend:
.int32 foo-10
.size negative_addend, 4
.globl foo
.globl bar
.export_name foo, foo

View File

@ -185,7 +185,7 @@ uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone,
if (D->segment && D->segment->outputSeg->isTLS())
return D->getOutputSegmentOffset() + reloc.Addend;
uint64_t value = D->getVA(reloc.Addend);
uint64_t value = D->getVA() + reloc.Addend;
if (reloc.Type == R_WASM_MEMORY_ADDR_LOCREL_I32) {
const auto *segment = cast<InputSegment>(chunk);
uint64_t p = segment->outputSeg->startVA + segment->outputSegmentOffset +

View File

@ -286,10 +286,10 @@ DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
function ? &function->signature : nullptr),
function(function) {}
uint64_t DefinedData::getVA(uint64_t addend) const {
uint64_t DefinedData::getVA() const {
LLVM_DEBUG(dbgs() << "getVA: " << getName() << "\n");
if (segment)
return segment->getVA(value + addend);
return segment->getVA(value);
return value;
}
@ -301,7 +301,7 @@ void DefinedData::setVA(uint64_t value_) {
uint64_t DefinedData::getOutputSegmentOffset() const {
LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
return segment->outputSegmentOffset + value;
return segment->getOffset(value);
}
uint64_t DefinedData::getOutputSegmentIndex() const {

View File

@ -290,7 +290,7 @@ public:
static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
// Returns the output virtual address of a defined data symbol.
uint64_t getVA(uint64_t addend = 0) const;
uint64_t getVA() const;
void setVA(uint64_t va);
// Returns the offset of a defined data symbol within its OutputSegment.