diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -47,6 +47,7 @@ ArrayRef getRelocations() const { return relocations; } void setRelocations(ArrayRef rs) { relocations = rs; } + uint64_t getOffset(uint64_t offset) const { return outSecOff + offset; } virtual StringRef getName() const = 0; virtual StringRef getDebugName() const = 0; virtual uint32_t getComdat() const = 0; @@ -58,8 +59,10 @@ ObjFile *file; OutputSection *outputSec = nullptr; - // Offset withing the output section - int32_t outputOffset = 0; + + // After assignAddresses is called, this represents the offset from + // the beginning of the output section this chunk was assigned to. + int32_t outSecOff = 0; // Signals that the section is part of the output. The garbage collector, // and COMDAT handling can set a sections' Live bit. @@ -108,7 +111,7 @@ uint32_t getInputSectionOffset() const override { return segment.SectionOffset; } - uint64_t getVA() const; + uint64_t getVA(uint64_t offset = 0) const; const OutputSegment *outputSeg = nullptr; int32_t outputSegmentOffset = 0; diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -122,7 +122,7 @@ // Copy this input chunk to an mmap'ed output file and apply relocations. void InputChunk::writeTo(uint8_t *buf) const { // Copy contents - memcpy(buf + outputOffset, data().data(), data().size()); + memcpy(buf + outSecOff, data().data(), data().size()); // Apply relocations if (relocations.empty()) @@ -134,7 +134,7 @@ LLVM_DEBUG(dbgs() << "applying relocations: " << toString(this) << " count=" << relocations.size() << "\n"); - int32_t off = outputOffset - getInputSectionOffset(); + int32_t off = outSecOff - getInputSectionOffset(); auto tombstone = getTombstone(); for (const WasmRelocation &rel : relocations) { @@ -196,7 +196,7 @@ if (relocations.empty()) return; - int32_t off = outputOffset - getInputSectionOffset(); + int32_t off = outSecOff - getInputSectionOffset(); LLVM_DEBUG(dbgs() << "writeRelocations: " << file->getName() << " offset=" << Twine(off) << "\n"); @@ -323,7 +323,7 @@ if (!file || !config->compressRelocations) return InputChunk::writeTo(buf); - buf += outputOffset; + buf += outSecOff; uint8_t *orig = buf; (void)orig; @@ -353,8 +353,8 @@ LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n"); } -uint64_t InputSegment::getVA() const { - return outputSeg->startVA + outputSegmentOffset; +uint64_t InputSegment::getVA(uint64_t offset) const { + return outputSeg->startVA + outputSegmentOffset + offset; } // Generate code to apply relocations to the data section at runtime. @@ -375,12 +375,11 @@ // TODO(sbc): Encode the relocations in the data section and write a loop // here to apply them. for (const WasmRelocation &rel : relocations) { - uint64_t offset = rel.Offset - getInputSectionOffset(); - uint64_t outputOffset = getVA() + offset; + uint64_t offset = getVA(rel.Offset) - getInputSectionOffset(); LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type) << " addend=" << rel.Addend << " index=" << rel.Index - << " output offset=" << outputOffset << "\n"); + << " output offset=" << offset << "\n"); // Get __memory_base writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); @@ -388,7 +387,7 @@ // Add the offset of the relocation writeU8(os, opcode_ptr_const, "CONST"); - writeSleb128(os, outputOffset, "offset"); + writeSleb128(os, offset, "offset"); writeU8(os, opcode_ptr_add, "ADD"); bool is64 = relocIs64(rel.Type); diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -128,7 +128,7 @@ case R_WASM_FUNCTION_OFFSET_I64: return reloc.Addend; case R_WASM_SECTION_OFFSET_I32: - return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend; + return getSectionSymbol(reloc.Index)->section->getOffset(reloc.Addend); default: llvm_unreachable("unexpected relocation type"); } @@ -245,7 +245,7 @@ // backward compat with old object files built with `-fPIC`. if (D->segment && D->segment->outputSeg->name == ".tdata") return D->getOutputSegmentOffset() + reloc.Addend; - return D->getVirtualAddress() + reloc.Addend; + return D->getVA(reloc.Addend); } case R_WASM_MEMORY_ADDR_TLS_SLEB: if (isa(sym) || sym->isUndefWeak()) @@ -266,11 +266,11 @@ case R_WASM_FUNCTION_OFFSET_I32: case R_WASM_FUNCTION_OFFSET_I64: { auto *f = cast(sym); - return f->function->outputOffset + - (f->function->getFunctionCodeOffset() + reloc.Addend); + return f->function->getOffset(f->function->getFunctionCodeOffset() + + reloc.Addend); } case R_WASM_SECTION_OFFSET_I32: - return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend; + return getSectionSymbol(reloc.Index)->section->getOffset(reloc.Addend); case R_WASM_TABLE_NUMBER_LEB: return getTableSymbol(reloc.Index)->getTableNumber(); default: diff --git a/lld/wasm/MapFile.cpp b/lld/wasm/MapFile.cpp --- a/lld/wasm/MapFile.cpp +++ b/lld/wasm/MapFile.cpp @@ -80,13 +80,13 @@ auto *chunk = syms[i]->getChunk(); if (chunk == nullptr) return; - uint64_t fileOffset = chunk->outputSec->getOffset() + chunk->outputOffset; + uint64_t fileOffset = chunk->outputSec->getOffset() + chunk->outSecOff; uint64_t vma = -1; uint64_t size = 0; if (auto *DD = dyn_cast(syms[i])) { - vma = DD->getVirtualAddress(); + vma = DD->getVA(); size = DD->getSize(); - fileOffset += DD->offset; + fileOffset += DD->value; } if (auto *DF = dyn_cast(syms[i])) { size = DF->function->getSize(); @@ -126,7 +126,7 @@ os << toString(*osec) << '\n'; if (auto *code = dyn_cast(osec)) { for (auto *chunk : code->functions) { - writeHeader(os, -1, chunk->outputSec->getOffset() + chunk->outputOffset, + writeHeader(os, -1, chunk->outputSec->getOffset() + chunk->outSecOff, chunk->getSize()); os.indent(8) << toString(chunk) << '\n'; for (Symbol *sym : sectionSyms[chunk]) @@ -139,7 +139,7 @@ os << oseg->name << '\n'; for (auto *chunk : oseg->inputSegments) { writeHeader(os, chunk->getVA(), - chunk->outputSec->getOffset() + chunk->outputOffset, + chunk->outputSec->getOffset() + chunk->outSecOff, chunk->getSize()); os.indent(8) << toString(chunk) << '\n'; for (Symbol *sym : sectionSyms[chunk]) diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -88,7 +88,7 @@ for (InputFunction *func : functions) { func->outputSec = this; - func->outputOffset = bodySize; + func->outSecOff = bodySize; func->calculateSize(); // All functions should have a non-empty body at this point assert(func->getSize()); @@ -180,8 +180,8 @@ for (InputSegment *inputSeg : segment->inputSegments) { inputSeg->outputSec = this; - inputSeg->outputOffset = segment->sectionOffset + segment->header.size() + - inputSeg->outputSegmentOffset; + inputSeg->outSecOff = segment->sectionOffset + segment->header.size() + + inputSeg->outputSegmentOffset; } } @@ -243,7 +243,7 @@ for (InputSection *section : inputSections) { assert(!section->discarded); section->outputSec = this; - section->outputOffset = payloadSize; + section->outSecOff = payloadSize; payloadSize += section->getSize(); } diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -234,7 +234,7 @@ return nullptr; LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); auto *rtn = replaceSymbol(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN); - rtn->setVirtualAddress(value); + rtn->setVA(value); rtn->referenced = true; return rtn; } diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -278,9 +278,9 @@ public: // Constructor for regular data symbols originating from input files. DefinedData(StringRef name, uint32_t flags, InputFile *f, - InputSegment *segment, uint64_t offset, uint64_t size) + InputSegment *segment, uint64_t value, uint64_t size) : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), - offset(offset), size(size) {} + value(value), size(size) {} // Constructor for linker synthetic data symbols. DefinedData(StringRef name, uint32_t flags) @@ -289,8 +289,8 @@ static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; } // Returns the output virtual address of a defined data symbol. - uint64_t getVirtualAddress() const; - void setVirtualAddress(uint64_t va); + uint64_t getVA(uint64_t addend = 0) const; + void setVA(uint64_t va); // Returns the offset of a defined data symbol within its OutputSegment. uint64_t getOutputSegmentOffset() const; @@ -298,7 +298,7 @@ uint64_t getSize() const { return size; } InputSegment *segment = nullptr; - uint32_t offset = 0; + uint64_t value = 0; protected: uint64_t size = 0; diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -276,22 +276,22 @@ function ? &function->signature : nullptr), function(function) {} -uint64_t DefinedData::getVirtualAddress() const { - LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); +uint64_t DefinedData::getVA(uint64_t addend) const { + LLVM_DEBUG(dbgs() << "getVA: " << getName() << "\n"); if (segment) - return segment->getVA() + offset; - return offset; + return segment->getVA(value + addend); + return value; } -void DefinedData::setVirtualAddress(uint64_t value) { - LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n"); +void DefinedData::setVA(uint64_t value_) { + LLVM_DEBUG(dbgs() << "setVA " << name << " -> " << value_ << "\n"); assert(!segment); - offset = value; + value = value_; } uint64_t DefinedData::getOutputSegmentOffset() const { LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); - return segment->outputSegmentOffset + offset; + return segment->outputSegmentOffset + value; } uint64_t DefinedData::getOutputSegmentIndex() const { diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -324,7 +324,7 @@ // Add the virtual address of the data symbol writeU8(os, opcode_ptr_const, "CONST"); - writeSleb128(os, d->getVirtualAddress(), "offset"); + writeSleb128(os, d->getVA(), "offset"); } else if (auto *f = dyn_cast(sym)) { if (f->isStub) continue; @@ -363,7 +363,7 @@ WasmInitExpr initExpr; initExpr.Opcode = WASM_OPCODE_I32_CONST; if (auto *d = dyn_cast(sym)) - initExpr.Value.Int32 = d->getVirtualAddress(); + initExpr.Value.Int32 = d->getVA(); else if (auto *f = dyn_cast(sym)) initExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex(); else { @@ -377,7 +377,7 @@ WasmGlobalType type{WASM_TYPE_I32, false}; WasmInitExpr initExpr; initExpr.Opcode = WASM_OPCODE_I32_CONST; - initExpr.Value.Int32 = sym->getVirtualAddress(); + initExpr.Value.Int32 = sym->getVA(); writeGlobalType(os, type); writeInitExpr(os, initExpr); } diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -252,14 +252,14 @@ } if (WasmSym::globalBase) - WasmSym::globalBase->setVirtualAddress(memoryPtr); + WasmSym::globalBase->setVA(memoryPtr); uint64_t dataStart = memoryPtr; // Arbitrarily set __dso_handle handle to point to the start of the data // segments. if (WasmSym::dsoHandle) - WasmSym::dsoHandle->setVirtualAddress(dataStart); + WasmSym::dsoHandle->setVA(dataStart); out.dylinkSec->memAlign = 0; for (OutputSegment *seg : segments) { @@ -291,14 +291,14 @@ WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol( "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN); WasmSym::initMemoryFlag->markLive(); - WasmSym::initMemoryFlag->setVirtualAddress(memoryPtr); + WasmSym::initMemoryFlag->setVA(memoryPtr); log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", "__wasm_init_memory_flag", memoryPtr, 4, 4)); memoryPtr += 4; } if (WasmSym::dataEnd) - WasmSym::dataEnd->setVirtualAddress(memoryPtr); + WasmSym::dataEnd->setVA(memoryPtr); uint64_t staticDataSize = memoryPtr - dataStart; log("mem: static data = " + Twine(staticDataSize)); @@ -313,7 +313,7 @@ // The fact that this comes last means that a malloc/brk implementation // can grow the heap at runtime. log("mem: heap base = " + Twine(memoryPtr)); - WasmSym::heapBase->setVirtualAddress(memoryPtr); + WasmSym::heapBase->setVA(memoryPtr); } uint64_t maxMemorySetting = 1ULL @@ -980,7 +980,7 @@ assert(WasmSym::initMemory); assert(WasmSym::initMemoryFlag); assert(hasPassiveInitializedSegments()); - uint64_t flagAddress = WasmSym::initMemoryFlag->getVirtualAddress(); + uint64_t flagAddress = WasmSym::initMemoryFlag->getVA(); bool is64 = config->is64.getValueOr(false); std::string bodyContent; { @@ -1369,7 +1369,7 @@ if (!config->isPic) { config->tableBase = 1; if (WasmSym::definedTableBase) - WasmSym::definedTableBase->setVirtualAddress(config->tableBase); + WasmSym::definedTableBase->setVA(config->tableBase); } log("-- createOutputSegments");