[lld] r243197 - COFF: Handle base relocation as a tuple of relocation type and RVA. NFC.

Rui Ueyama ruiu at google.com
Fri Jul 24 18:44:33 PDT 2015


Author: ruiu
Date: Fri Jul 24 20:44:32 2015
New Revision: 243197

URL: http://llvm.org/viewvc/llvm-project?rev=243197&view=rev
Log:
COFF: Handle base relocation as a tuple of relocation type and RVA. NFC.

On x64 and x86, we use only one base relocation type, so we handled
base relocations just as a list of RVAs. That doesn't work well for
ARM becuase we have to handle two types of base relocations on ARM.
This patch changes the type of base relocation from uint32_t to
{reltype, uint32_t} to make it easy to port this code to ARM.

Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/Writer.cpp
    lld/trunk/COFF/Writer.h

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=243197&r1=243196&r2=243197&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Fri Jul 24 20:44:32 2015
@@ -115,12 +115,16 @@ void SectionChunk::addAssociative(Sectio
   Child->Root = false;
 }
 
-static bool isAbs(const coff_relocation &Rel) {
+static uint8_t getBaserelType(const coff_relocation &Rel) {
   switch (Config->MachineType) {
   case IMAGE_FILE_MACHINE_AMD64:
-    return Rel.Type == IMAGE_REL_AMD64_ADDR64;
+    if (Rel.Type == IMAGE_REL_AMD64_ADDR64)
+      return IMAGE_REL_BASED_DIR64;
+    return IMAGE_REL_BASED_ABSOLUTE;
   case IMAGE_FILE_MACHINE_I386:
-    return Rel.Type == IMAGE_REL_I386_DIR32;
+    if (Rel.Type == IMAGE_REL_I386_DIR32)
+      return IMAGE_REL_BASED_HIGHLOW;
+    return IMAGE_REL_BASED_ABSOLUTE;
   default:
     llvm_unreachable("unknown machine type");
   }
@@ -130,14 +134,15 @@ static bool isAbs(const coff_relocation
 // Collect all locations that contain absolute addresses, which need to be
 // fixed by the loader if load-time relocation is needed.
 // Only called when base relocation is enabled.
-void SectionChunk::getBaserels(std::vector<uint32_t> *Res) {
+void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
   for (const coff_relocation &Rel : Relocs) {
-    if (!isAbs(Rel))
+    uint8_t Ty = getBaserelType(Rel);
+    if (Ty == IMAGE_REL_BASED_ABSOLUTE)
       continue;
     SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
     if (isa<DefinedAbsolute>(Body))
       continue;
-    Res->push_back(RVA + Rel.VirtualAddress);
+    Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
   }
 }
 
@@ -258,8 +263,8 @@ void ImportThunkChunkX64::writeTo(uint8_
   write32le(Buf + FileOff + 2, ImpSymbol->getRVA() - RVA - getSize());
 }
 
-void ImportThunkChunkX86::getBaserels(std::vector<uint32_t> *Res) {
-  Res->push_back(getRVA() + 2);
+void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {
+  Res->emplace_back(getRVA() + 2);
 }
 
 void ImportThunkChunkX86::writeTo(uint8_t *Buf) {
@@ -268,8 +273,8 @@ void ImportThunkChunkX86::writeTo(uint8_
   write32le(Buf + FileOff + 2, ImpSymbol->getRVA() + Config->ImageBase);
 }
 
-void LocalImportChunk::getBaserels(std::vector<uint32_t> *Res) {
-  Res->push_back(getRVA());
+void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
+  Res->emplace_back(getRVA());
 }
 
 size_t LocalImportChunk::getSize() const {
@@ -294,7 +299,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf
 
 // Windows-specific.
 // This class represents a block in .reloc section.
-BaserelChunk::BaserelChunk(uint32_t Page, uint32_t *Begin, uint32_t *End) {
+BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
   // Block header consists of 4 byte page RVA and 4 byte block size.
   // Each entry is 2 byte. Last entry may be padding.
   Data.resize(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
@@ -302,17 +307,8 @@ BaserelChunk::BaserelChunk(uint32_t Page
   write32le(P, Page);
   write32le(P + 4, Data.size());
   P += 8;
-  for (uint32_t *I = Begin; I != End; ++I) {
-    switch (Config->MachineType) {
-    case AMD64:
-      write16le(P, (IMAGE_REL_BASED_DIR64 << 12) | (*I - Page));
-      break;
-    case I386:
-      write16le(P, (IMAGE_REL_BASED_HIGHLOW << 12) | (*I - Page));
-      break;
-    default:
-      llvm_unreachable("unsupported machine type");
-    }
+  for (Baserel *I = Begin; I != End; ++I) {
+    write16le(P, (I->Type << 12) | (I->RVA - Page));
     P += 2;
   }
 }
@@ -321,5 +317,16 @@ void BaserelChunk::writeTo(uint8_t *Buf)
   memcpy(Buf + FileOff, Data.data(), Data.size());
 }
 
+uint8_t Baserel::getDefaultType() {
+  switch (Config->MachineType) {
+  case IMAGE_FILE_MACHINE_AMD64:
+    return IMAGE_REL_BASED_DIR64;
+  case IMAGE_FILE_MACHINE_I386:
+    return IMAGE_REL_BASED_HIGHLOW;
+  default:
+    llvm_unreachable("unknown machine type");
+  }
+}
+
 } // namespace coff
 } // namespace lld

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=243197&r1=243196&r2=243197&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Fri Jul 24 20:44:32 2015
@@ -29,9 +29,10 @@ using llvm::object::coff_relocation;
 using llvm::object::coff_section;
 using llvm::sys::fs::file_magic;
 
+class Baserel;
 class Defined;
-class DefinedRegular;
 class DefinedImportData;
+class DefinedRegular;
 class ObjectFile;
 class OutputSection;
 class SymbolBody;
@@ -83,7 +84,7 @@ public:
 
   // Windows-specific.
   // Collect all locations that contain absolute addresses for base relocations.
-  virtual void getBaserels(std::vector<uint32_t> *Res) {}
+  virtual void getBaserels(std::vector<Baserel> *Res) {}
 
   // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
   // bytes, so this is used only for logging or debugging.
@@ -134,7 +135,7 @@ public:
   bool hasData() const override;
   uint32_t getPermissions() const override;
   StringRef getSectionName() const override { return SectionName; }
-  void getBaserels(std::vector<uint32_t> *Res) override;
+  void getBaserels(std::vector<Baserel> *Res) override;
   bool isCOMDAT() const;
   void applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
   void applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
@@ -244,7 +245,7 @@ class ImportThunkChunkX86 : public Chunk
 public:
   explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}
   size_t getSize() const override { return sizeof(ImportThunkX86); }
-  void getBaserels(std::vector<uint32_t> *Res) override;
+  void getBaserels(std::vector<Baserel> *Res) override;
   void writeTo(uint8_t *Buf) override;
 
 private:
@@ -257,7 +258,7 @@ class LocalImportChunk : public Chunk {
 public:
   explicit LocalImportChunk(Defined *S) : Sym(S) {}
   size_t getSize() const override;
-  void getBaserels(std::vector<uint32_t> *Res) override;
+  void getBaserels(std::vector<Baserel> *Res) override;
   void writeTo(uint8_t *Buf) override;
 
 private:
@@ -282,7 +283,7 @@ private:
 // See the PE/COFF spec 5.6 for details.
 class BaserelChunk : public Chunk {
 public:
-  BaserelChunk(uint32_t Page, uint32_t *Begin, uint32_t *End);
+  BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End);
   size_t getSize() const override { return Data.size(); }
   void writeTo(uint8_t *Buf) override;
 
@@ -290,6 +291,16 @@ private:
   std::vector<uint8_t> Data;
 };
 
+class Baserel {
+public:
+  Baserel(uint32_t V, uint8_t Ty) : RVA(V), Type(Ty) {}
+  explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {}
+  uint8_t getDefaultType();
+
+  uint32_t RVA;
+  uint8_t Type;
+};
+
 } // namespace coff
 } // namespace lld
 

Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=243197&r1=243196&r2=243197&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Fri Jul 24 20:44:32 2015
@@ -319,9 +319,9 @@ public:
     write32le(Buf + FileOff + 13, Helper->getRVA() - RVA - 17);
   }
 
-  void getBaserels(std::vector<uint32_t> *Res) override {
-    Res->push_back(RVA + 3);
-    Res->push_back(RVA + 8);
+  void getBaserels(std::vector<Baserel> *Res) override {
+    Res->emplace_back(RVA + 3);
+    Res->emplace_back(RVA + 8);
   }
 
   Defined *Imp = nullptr;
@@ -367,8 +367,8 @@ public:
     write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
   }
 
-  void getBaserels(std::vector<uint32_t> *Res) override {
-    Res->push_back(RVA);
+  void getBaserels(std::vector<Baserel> *Res) override {
+    Res->emplace_back(RVA);
   }
 
   Chunk *Thunk;

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=243197&r1=243196&r2=243197&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Jul 24 20:44:32 2015
@@ -618,7 +618,7 @@ OutputSection *Writer::createSection(Str
 
 // Dest is .reloc section. Add contents to that section.
 void Writer::addBaserels(OutputSection *Dest) {
-  std::vector<uint32_t> V;
+  std::vector<Baserel> V;
   for (OutputSection *Sec : OutputSections) {
     if (Sec == Dest)
       continue;
@@ -633,12 +633,12 @@ void Writer::addBaserels(OutputSection *
 }
 
 // Add addresses to .reloc section. Note that addresses are grouped by page.
-void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V) {
+void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
   const uint32_t Mask = ~uint32_t(PageSize - 1);
-  uint32_t Page = V[0] & Mask;
+  uint32_t Page = V[0].RVA & Mask;
   size_t I = 0, J = 1;
   for (size_t E = V.size(); J < E; ++J) {
-    uint32_t P = V[J] & Mask;
+    uint32_t P = V[J].RVA & Mask;
     if (P == Page)
       continue;
     BaserelChunk *Buf = BAlloc.Allocate();

Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=243197&r1=243196&r2=243197&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Fri Jul 24 20:44:32 2015
@@ -100,7 +100,7 @@ private:
   OutputSection *findSection(StringRef Name);
   OutputSection *createSection(StringRef Name);
   void addBaserels(OutputSection *Dest);
-  void addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V);
+  void addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V);
 
   uint32_t getSizeOfInitializedData();
   std::map<StringRef, std::vector<DefinedImportData *>> binImports();





More information about the llvm-commits mailing list