[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