[lld] r322212 - [WebAssembly] Move relocation handling InputChunks.cpp
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 11:22:42 PST 2018
Author: sbc
Date: Wed Jan 10 11:22:42 2018
New Revision: 322212
URL: http://llvm.org/viewvc/llvm-project?rev=322212&view=rev
Log:
[WebAssembly] Move relocation handling InputChunks.cpp
Teach each input chunk how to write itself and apply its
own relocations.
Differential Revision: https://reviews.llvm.org/D41891
Modified:
lld/trunk/wasm/InputChunks.cpp
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
lld/trunk/wasm/OutputSections.cpp
Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=322212&r1=322211&r2=322212&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Wed Jan 10 11:22:42 2018
@@ -8,17 +8,22 @@
//===----------------------------------------------------------------------===//
#include "InputChunks.h"
+#include "Config.h"
#include "OutputSegment.h"
+#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h"
+#include "llvm/Support/LEB128.h"
#define DEBUG_TYPE "lld"
using namespace llvm;
+using namespace llvm::wasm;
+using namespace lld;
using namespace lld::wasm;
uint32_t InputSegment::translateVA(uint32_t Address) const {
assert(Address >= startVA() && Address < endVA());
- int32_t Delta = OutputSeg->StartVA + OutputOffset - startVA();
+ int32_t Delta = OutputSeg->StartVA + OutputSegmentOffset - startVA();
DEBUG(dbgs() << "translateVA: " << getName() << " Delta=" << Delta
<< " Address=" << Address << "\n");
return Address + Delta;
@@ -31,3 +36,87 @@ void InputChunk::copyRelocations(const W
if (R.Offset >= Start && R.Offset < Start + Size)
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;
+ int64_t ExistingValue;
+ switch (Reloc.Reloc.Type) {
+ case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ ExistingValue = decodeULEB128(Buf);
+ if (ExistingValue != Reloc.Reloc.Index) {
+ DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n");
+ assert(decodeULEB128(Buf) == Reloc.Reloc.Index);
+ }
+ LLVM_FALLTHROUGH;
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ encodeULEB128(Reloc.Value, Buf, 5);
+ break;
+ case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ ExistingValue = decodeSLEB128(Buf);
+ if (ExistingValue != Reloc.Reloc.Index) {
+ DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n");
+ assert(decodeSLEB128(Buf) == Reloc.Reloc.Index);
+ }
+ LLVM_FALLTHROUGH;
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ encodeSLEB128(static_cast<int32_t>(Reloc.Value), Buf, 5);
+ break;
+ case R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ support::endian::write32<support::little>(Buf, Reloc.Value);
+ break;
+ default:
+ llvm_unreachable("unknown relocation type");
+ }
+}
+
+static void applyRelocations(uint8_t *Buf, ArrayRef<OutputRelocation> Relocs) {
+ if (!Relocs.size())
+ return;
+ log("applyRelocations: count=" + Twine(Relocs.size()));
+ for (const OutputRelocation &Reloc : Relocs)
+ applyRelocation(Buf, Reloc);
+}
+
+void InputChunk::writeTo(uint8_t *SectionStart) const {
+ memcpy(SectionStart + getOutputOffset(), getData(), getSize());
+ applyRelocations(SectionStart, OutRelocations);
+}
+
+// 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() {
+ int32_t Off = getOutputOffset() - getInputSectionOffset();
+ log("calcRelocations: " + File.getName() + " offset=" + Twine(Off));
+ 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->EmitRelocs)
+ NewReloc.NewIndex = File.calcNewIndex(Reloc);
+
+ switch (Reloc.Type) {
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend;
+ break;
+ default:
+ NewReloc.Value = File.calcNewIndex(Reloc);
+ break;
+ }
+
+ OutRelocations.emplace_back(NewReloc);
+ }
+}
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=322212&r1=322211&r2=322212&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Wed Jan 10 11:22:42 2018
@@ -34,17 +34,30 @@ class OutputSegment;
class InputChunk {
public:
- InputChunk(const ObjFile &F) : File(F) {}
- virtual ~InputChunk() = default;
+ virtual uint32_t getSize() const = 0;
+
void copyRelocations(const WasmSection &Section);
+ void writeTo(uint8_t *SectionStart) const;
+
+ void setOutputOffset(uint32_t Offset) {
+ OutputOffset = Offset;
+ calcRelocations();
+ }
+
+ uint32_t getOutputOffset() const { return OutputOffset; }
+
+ std::vector<OutputRelocation> OutRelocations;
+
+protected:
+ InputChunk(const ObjFile &F) : File(F) {}
+ virtual ~InputChunk() = default;
+ void calcRelocations();
virtual const uint8_t *getData() const = 0;
- virtual uint32_t getSize() const = 0;
virtual uint32_t getInputSectionOffset() const = 0;
- int32_t OutputOffset = 0;
std::vector<WasmRelocation> Relocations;
- std::vector<OutputRelocation> OutRelocations;
+ int32_t OutputOffset = 0;
const ObjFile &File;
};
@@ -69,22 +82,24 @@ public:
void setOutputSegment(const OutputSegment *Segment, uint32_t Offset) {
OutputSeg = Segment;
- OutputOffset = Offset;
+ OutputSegmentOffset = Offset;
}
const uint8_t *getData() const override {
return Segment.Data.Content.data();
}
uint32_t getSize() const override { return Segment.Data.Content.size(); }
- uint32_t getInputSectionOffset() const override {
- return Segment.SectionOffset;
- }
uint32_t getAlignment() const { return Segment.Data.Alignment; }
uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; }
uint32_t endVA() const { return startVA() + getSize(); }
StringRef getName() const { return Segment.Data.Name; }
+ int32_t OutputSegmentOffset = 0;
+
protected:
+ uint32_t getInputSectionOffset() const override {
+ return Segment.SectionOffset;
+ }
const WasmSegment &Segment;
const OutputSegment *OutputSeg = nullptr;
};
@@ -99,11 +114,8 @@ public:
uint32_t getSize() const override { return Function.Size; }
const uint8_t *getData() const override {
- return File.CodeSection->Content.data() + Function.CodeSectionOffset;
+ return File.CodeSection->Content.data() + getInputSectionOffset();
}
- uint32_t getInputSectionOffset() const override {
- return Function.CodeSectionOffset;
- };
uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
bool hasOutputIndex() const { return OutputIndex.hasValue(); };
@@ -115,6 +127,9 @@ public:
const WasmSignature &Signature;
protected:
+ uint32_t getInputSectionOffset() const override {
+ return Function.CodeSectionOffset;
+ }
const WasmFunction &Function;
llvm::Optional<uint32_t> OutputIndex;
};
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=322212&r1=322211&r2=322212&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Wed Jan 10 11:22:42 2018
@@ -83,6 +83,29 @@ uint32_t ObjFile::relocateGlobalIndex(ui
return Index;
}
+// Relocations contain an index into the function, global or table index
+// space of the input file. This function takes a relocation and returns the
+// relocated index (i.e. translates from the input index space to the output
+// index space).
+uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
+ switch (Reloc.Type) {
+ case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ return relocateTypeIndex(Reloc.Index);
+ case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ return relocateFunctionIndex(Reloc.Index);
+ case R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ return relocateTableIndex(Reloc.Index);
+ case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ return relocateGlobalIndex(Reloc.Index);
+ default:
+ llvm_unreachable("unknown relocation type");
+ }
+}
+
void ObjFile::parse() {
// Parse a memory buffer as a wasm file.
DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=322212&r1=322211&r2=322212&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Wed Jan 10 11:22:42 2018
@@ -28,6 +28,7 @@ using llvm::object::WasmSection;
using llvm::object::WasmSymbol;
using llvm::wasm::WasmImport;
using llvm::wasm::WasmSignature;
+using llvm::wasm::WasmRelocation;
namespace lld {
namespace wasm {
@@ -91,11 +92,9 @@ public:
void dumpInfo() const;
- uint32_t relocateTypeIndex(uint32_t Original) const;
uint32_t relocateFunctionIndex(uint32_t Original) const;
- uint32_t relocateGlobalIndex(uint32_t Original) const;
- uint32_t relocateTableIndex(uint32_t Original) const;
uint32_t getRelocatedAddress(uint32_t Index) const;
+ uint32_t calcNewIndex(const WasmRelocation &Reloc) const;
const WasmSection *CodeSection = nullptr;
const WasmSection *DataSection = nullptr;
@@ -108,6 +107,10 @@ public:
ArrayRef<Symbol *> getTableSymbols() { return TableSymbols; }
private:
+ uint32_t relocateTypeIndex(uint32_t Original) const;
+ uint32_t relocateGlobalIndex(uint32_t Original) const;
+ uint32_t relocateTableIndex(uint32_t Original) const;
+
Symbol *createDefined(const WasmSymbol &Sym, Symbol::Kind Kind,
const InputSegment *Segment = nullptr,
InputFunction *Function = nullptr,
Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=322212&r1=322211&r2=322212&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Wed Jan 10 11:22:42 2018
@@ -9,16 +9,12 @@
#include "OutputSections.h"
-#include "Config.h"
#include "InputChunks.h"
#include "InputFiles.h"
#include "OutputSegment.h"
-#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
#include "lld/Common/Threads.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/LEB128.h"
#define DEBUG_TYPE "lld"
@@ -27,12 +23,6 @@ using namespace llvm::wasm;
using namespace lld;
using namespace lld::wasm;
-enum class RelocEncoding {
- Uleb128,
- Sleb128,
- I32,
-};
-
static StringRef sectionTypeToString(uint32_t SectionType) {
switch (SectionType) {
case WASM_SEC_CUSTOM:
@@ -71,110 +61,6 @@ std::string lld::toString(const OutputSe
return rtn;
}
-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;
- int64_t ExistingValue;
- switch (Reloc.Reloc.Type) {
- case R_WEBASSEMBLY_TYPE_INDEX_LEB:
- case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
- ExistingValue = decodeULEB128(Buf);
- if (ExistingValue != Reloc.Reloc.Index) {
- DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n");
- assert(decodeULEB128(Buf) == Reloc.Reloc.Index);
- }
- LLVM_FALLTHROUGH;
- case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
- case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- encodeULEB128(Reloc.Value, Buf, 5);
- break;
- case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- ExistingValue = decodeSLEB128(Buf);
- if (ExistingValue != Reloc.Reloc.Index) {
- DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n");
- assert(decodeSLEB128(Buf) == Reloc.Reloc.Index);
- }
- LLVM_FALLTHROUGH;
- case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
- encodeSLEB128(static_cast<int32_t>(Reloc.Value), Buf, 5);
- break;
- case R_WEBASSEMBLY_TABLE_INDEX_I32:
- case R_WEBASSEMBLY_MEMORY_ADDR_I32:
- support::endian::write32<support::little>(Buf, Reloc.Value);
- break;
- default:
- llvm_unreachable("unknown relocation type");
- }
-}
-
-static void applyRelocations(uint8_t *Buf, ArrayRef<OutputRelocation> Relocs) {
- if (!Relocs.size())
- return;
- log("applyRelocations: count=" + Twine(Relocs.size()));
- for (const OutputRelocation &Reloc : Relocs)
- applyRelocation(Buf, Reloc);
-}
-
-// Relocations contain an index into the function, global or table index
-// space of the input file. This function takes a relocation and returns the
-// relocated index (i.e. translates from the input index space to the output
-// index space).
-static uint32_t calcNewIndex(const ObjFile &File, const WasmRelocation &Reloc) {
- switch (Reloc.Type) {
- case R_WEBASSEMBLY_TYPE_INDEX_LEB:
- return File.relocateTypeIndex(Reloc.Index);
- case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
- return File.relocateFunctionIndex(Reloc.Index);
- case R_WEBASSEMBLY_TABLE_INDEX_I32:
- case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- return File.relocateTableIndex(Reloc.Index);
- case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
- case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
- case R_WEBASSEMBLY_MEMORY_ADDR_I32:
- return File.relocateGlobalIndex(Reloc.Index);
- default:
- llvm_unreachable("unknown relocation type");
- }
-}
-
-// Take a vector of relocations from an input file and create output
-// relocations based on them. Calculates the updated index and offset for
-// each relocation as well as the value to write out in the final binary.
-static void calcRelocations(const ObjFile &File,
- ArrayRef<WasmRelocation> Relocs,
- std::vector<OutputRelocation> &OutputRelocs,
- int32_t OutputOffset) {
- log("calcRelocations: " + File.getName() + " offset=" + Twine(OutputOffset));
- for (const WasmRelocation &Reloc : Relocs) {
- OutputRelocation NewReloc;
- NewReloc.Reloc = Reloc;
- assert(Reloc.Offset + OutputOffset > 0);
- NewReloc.Reloc.Offset += OutputOffset;
- DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index
- << " offset=" << Reloc.Offset
- << " newOffset=" << NewReloc.Reloc.Offset << "\n");
-
- if (Config->EmitRelocs)
- NewReloc.NewIndex = calcNewIndex(File, Reloc);
-
- switch (Reloc.Type) {
- case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
- case R_WEBASSEMBLY_MEMORY_ADDR_I32:
- case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
- NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend;
- break;
- default:
- NewReloc.Value = calcNewIndex(File, Reloc);
- break;
- }
-
- OutputRelocs.emplace_back(NewReloc);
- }
-}
-
std::string OutputSection::getSectionName() const {
return sectionTypeToString(Type);
}
@@ -203,9 +89,7 @@ CodeSection::CodeSection(ArrayRef<InputF
BodySize = CodeSectionHeader.size();
for (InputChunk *Func : Functions) {
- Func->OutputOffset = BodySize;
- calcRelocations(Func->File, Func->Relocations, Func->OutRelocations,
- Func->OutputOffset - Func->getInputSectionOffset());
+ Func->setOutputOffset(BodySize);
BodySize += Func->getSize();
}
@@ -230,10 +114,8 @@ void CodeSection::writeTo(uint8_t *Buf)
Buf += CodeSectionHeader.size();
// Write code section bodies
- parallelForEach(Functions, [ContentsStart](InputChunk *Func) {
- memcpy(ContentsStart + Func->OutputOffset, Func->getData(),
- Func->getSize());
- applyRelocations(ContentsStart, Func->OutRelocations);
+ parallelForEach(Functions, [ContentsStart](const InputChunk *Chunk) {
+ Chunk->writeTo(ContentsStart);
});
}
@@ -267,16 +149,12 @@ DataSection::DataSection(ArrayRef<Output
writeUleb128(OS, Segment->Size, "segment size");
OS.flush();
Segment->setSectionOffset(BodySize);
- BodySize += Segment->Header.size();
+ BodySize += Segment->Header.size() + Segment->Size;
log("Data segment: size=" + Twine(Segment->Size));
- for (InputChunk *InputSeg : Segment->InputSegments) {
- uint32_t OutputOffset = Segment->getSectionOffset() +
- Segment->Header.size() + InputSeg->OutputOffset;
- calcRelocations(InputSeg->File, InputSeg->Relocations,
- InputSeg->OutRelocations,
- OutputOffset - InputSeg->getInputSectionOffset());
- }
- BodySize += Segment->Size;
+ for (InputSegment *InputSeg : Segment->InputSegments)
+ InputSeg->setOutputOffset(Segment->getSectionOffset() +
+ Segment->Header.size() +
+ InputSeg->OutputSegmentOffset);
}
createHeader(BodySize);
@@ -302,11 +180,8 @@ void DataSection::writeTo(uint8_t *Buf)
memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
// Write segment data payload
- for (const InputChunk *Input : Segment->InputSegments) {
- memcpy(SegStart + Segment->Header.size() + Input->OutputOffset,
- Input->getData(), Input->getSize());
- applyRelocations(ContentsStart, Input->OutRelocations);
- }
+ for (const InputChunk *Chunk : Segment->InputSegments)
+ Chunk->writeTo(ContentsStart);
});
}
More information about the llvm-commits
mailing list