Index: lld/trunk/wasm/InputChunks.h =================================================================== --- lld/trunk/wasm/InputChunks.h +++ lld/trunk/wasm/InputChunks.h @@ -27,6 +27,10 @@ using llvm::wasm::WasmSignature; using llvm::object::WasmSection; +namespace llvm { +class raw_ostream; +} + namespace lld { namespace wasm { @@ -45,19 +49,16 @@ void writeTo(uint8_t *SectionStart) const; - void setOutputOffset(uint32_t Offset) { - OutputOffset = Offset; - calcRelocations(); - } - - uint32_t getOutputOffset() const { return OutputOffset; } ArrayRef getRelocations() const { return Relocations; } virtual StringRef getComdat() const = 0; virtual StringRef getName() const = 0; - std::vector OutRelocations; + size_t NumRelocations() const { return Relocations.size(); } + void writeRelocations(llvm::raw_ostream &OS) const; + ObjFile *File; + int32_t OutputOffset = 0; // Signals that the section is part of the output. The garbage collector, // and COMDAT handling can set a sections' Live bit. @@ -68,12 +69,10 @@ InputChunk(ObjFile *F, Kind K) : File(F), Live(!Config->GcSections), SectionKind(K) {} virtual ~InputChunk() = default; - void calcRelocations(); virtual ArrayRef data() const = 0; virtual uint32_t getInputSectionOffset() const = 0; std::vector Relocations; - int32_t OutputOffset = 0; Kind SectionKind; }; Index: lld/trunk/wasm/InputChunks.cpp =================================================================== --- lld/trunk/wasm/InputChunks.cpp +++ lld/trunk/wasm/InputChunks.cpp @@ -10,6 +10,7 @@ #include "InputChunks.h" #include "Config.h" #include "OutputSegment.h" +#include "WriterUtils.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/LLVM.h" #include "llvm/Support/LEB128.h" @@ -44,76 +45,69 @@ Relocations.push_back(R); } -static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) { - DEBUG(dbgs() << "write reloc: type=" << Reloc.Reloc.Type - << " index=" << Reloc.Reloc.Index << " value=" << Reloc.Value - << " offset=" << Reloc.Reloc.Offset << "\n"); - - Buf += Reloc.Reloc.Offset; - - switch (Reloc.Reloc.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - // Additional check to verify that the existing value that the location - // matches our expectations. - if (decodeULEB128(Buf) != Reloc.Reloc.Index) { - DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n"); - assert(decodeULEB128(Buf) == Reloc.Reloc.Index); - } - LLVM_FALLTHROUGH; - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - encodeULEB128(Reloc.Value, Buf, 5); - break; - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - encodeSLEB128(static_cast(Reloc.Value), Buf, 5); - break; - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - write32le(Buf, Reloc.Value); - break; - default: - llvm_unreachable("unknown relocation type"); - } -} - -// Copy this input chunk to an mmap'ed output file. +// Copy this input chunk to an mmap'ed output file and apply relocations. void InputChunk::writeTo(uint8_t *Buf) const { // Copy contents - memcpy(Buf + getOutputOffset(), data().data(), data().size()); + memcpy(Buf + OutputOffset, data().data(), data().size()); // Apply relocations - if (OutRelocations.empty()) + if (Relocations.empty()) return; - DEBUG(dbgs() << "applyRelocations: count=" << OutRelocations.size() << "\n"); - for (const OutputRelocation &Reloc : OutRelocations) - applyRelocation(Buf, Reloc); + + DEBUG(dbgs() << "applyRelocations: count=" << Relocations.size() << "\n"); + int32_t Off = OutputOffset - getInputSectionOffset(); + + for (const WasmRelocation &Rel : Relocations) { + uint8_t *Loc = Buf + Rel.Offset + Off; + uint64_t Value = File->calcNewValue(Rel); + + DEBUG(dbgs() << "write reloc: type=" << Rel.Type << " index=" << Rel.Index + << " value=" << Value << " offset=" << Rel.Offset << "\n"); + + switch (Rel.Type) { + case R_WEBASSEMBLY_TYPE_INDEX_LEB: + case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + case R_WEBASSEMBLY_MEMORY_ADDR_LEB: + encodeULEB128(Value, Loc, 5); + break; + case R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + encodeSLEB128(static_cast(Value), Loc, 5); + break; + case R_WEBASSEMBLY_TABLE_INDEX_I32: + case R_WEBASSEMBLY_MEMORY_ADDR_I32: + write32le(Loc, Value); + break; + default: + llvm_unreachable("unknown relocation type"); + } + } } -// Populate OutRelocations based on the input relocations and offset within the -// output section. Calculates the updated index and offset for each relocation -// as well as the value to write out in the final binary. -void InputChunk::calcRelocations() { +// Copy relocation entries to a given output stream. +// This function is used only when a user passes "-r". For a regular link, +// we consume relocations instead of copying them to an output file. +void InputChunk::writeRelocations(raw_ostream &OS) const { if (Relocations.empty()) return; - int32_t Off = getOutputOffset() - getInputSectionOffset(); - DEBUG(dbgs() << "calcRelocations: " << File->getName() - << " offset=" << Twine(Off) << "\n"); - for (const WasmRelocation &Reloc : Relocations) { - OutputRelocation NewReloc; - NewReloc.Reloc = Reloc; - assert(Reloc.Offset + Off > 0); - NewReloc.Reloc.Offset += Off; - DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index - << " offset=" << Reloc.Offset - << " newOffset=" << NewReloc.Reloc.Offset << "\n"); - if (Config->Relocatable) - NewReloc.NewIndex = File->calcNewIndex(Reloc); + int32_t Off = OutputOffset - getInputSectionOffset(); + DEBUG(dbgs() << "writeRelocations: " << File->getName() + << " offset=" << Twine(Off) << "\n"); - NewReloc.Value = File->calcNewValue(Reloc); - OutRelocations.emplace_back(NewReloc); + for (const WasmRelocation &Rel : Relocations) { + writeUleb128(OS, Rel.Type, "reloc type"); + writeUleb128(OS, Rel.Offset + Off, "reloc offset"); + writeUleb128(OS, File->calcNewIndex(Rel), "reloc index"); + + switch (Rel.Type) { + case R_WEBASSEMBLY_MEMORY_ADDR_LEB: + case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case R_WEBASSEMBLY_MEMORY_ADDR_I32: + writeUleb128(OS, Rel.Addend, "reloc addend"); + break; + } } } Index: lld/trunk/wasm/OutputSections.cpp =================================================================== --- lld/trunk/wasm/OutputSections.cpp +++ lld/trunk/wasm/OutputSections.cpp @@ -90,7 +90,7 @@ BodySize = CodeSectionHeader.size(); for (InputChunk *Func : Functions) { - Func->setOutputOffset(BodySize); + Func->OutputOffset = BodySize; BodySize += Func->getSize(); } @@ -123,14 +123,13 @@ uint32_t CodeSection::numRelocations() const { uint32_t Count = 0; for (const InputChunk *Func : Functions) - Count += Func->OutRelocations.size(); + Count += Func->NumRelocations(); return Count; } void CodeSection::writeRelocations(raw_ostream &OS) const { - for (const InputChunk *Func : Functions) - for (const OutputRelocation &Reloc : Func->OutRelocations) - writeReloc(OS, Reloc); + for (const InputChunk *C : Functions) + C->writeRelocations(OS); } DataSection::DataSection(ArrayRef Segments) @@ -153,9 +152,9 @@ BodySize += Segment->Header.size() + Segment->Size; log("Data segment: size=" + Twine(Segment->Size)); for (InputSegment *InputSeg : Segment->InputSegments) - InputSeg->setOutputOffset(Segment->getSectionOffset() + - Segment->Header.size() + - InputSeg->OutputSegmentOffset); + InputSeg->OutputOffset = Segment->getSectionOffset() + + Segment->Header.size() + + InputSeg->OutputSegmentOffset; } createHeader(BodySize); @@ -190,13 +189,12 @@ uint32_t Count = 0; for (const OutputSegment *Seg : Segments) for (const InputChunk *InputSeg : Seg->InputSegments) - Count += InputSeg->OutRelocations.size(); + Count += InputSeg->NumRelocations(); return Count; } void DataSection::writeRelocations(raw_ostream &OS) const { for (const OutputSegment *Seg : Segments) - for (const InputChunk *InputSeg : Seg->InputSegments) - for (const OutputRelocation &Reloc : InputSeg->OutRelocations) - writeReloc(OS, Reloc); + for (const InputChunk *C : Seg->InputSegments) + C->writeRelocations(OS); } Index: lld/trunk/wasm/WriterUtils.h =================================================================== --- lld/trunk/wasm/WriterUtils.h +++ lld/trunk/wasm/WriterUtils.h @@ -31,12 +31,6 @@ namespace lld { namespace wasm { -struct OutputRelocation { - llvm::wasm::WasmRelocation Reloc; - uint32_t NewIndex; - uint32_t Value; -}; - void debugWrite(uint64_t Offset, const Twine &Msg); void writeUleb128(raw_ostream &OS, uint32_t Number, StringRef Msg); @@ -67,8 +61,6 @@ void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export); -void writeReloc(raw_ostream &OS, const OutputRelocation &Reloc); - } // namespace wasm std::string toString(const llvm::wasm::ValType Type); Index: lld/trunk/wasm/WriterUtils.cpp =================================================================== --- lld/trunk/wasm/WriterUtils.cpp +++ lld/trunk/wasm/WriterUtils.cpp @@ -162,23 +162,6 @@ fatal("unsupported export type: " + Twine(Export.Kind)); } } - -void wasm::writeReloc(raw_ostream &OS, const OutputRelocation &Reloc) { - writeUleb128(OS, Reloc.Reloc.Type, "reloc type"); - writeUleb128(OS, Reloc.Reloc.Offset, "reloc offset"); - writeUleb128(OS, Reloc.NewIndex, "reloc index"); - - switch (Reloc.Reloc.Type) { - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - writeUleb128(OS, Reloc.Reloc.Addend, "reloc addend"); - break; - default: - break; - } -} - } // namespace lld std::string lld::toString(ValType Type) {