[lld] r243176 - COFF: Fix __ImageBase symbol relocation.

Rui Ueyama ruiu at google.com
Fri Jul 24 15:58:44 PDT 2015


Author: ruiu
Date: Fri Jul 24 17:58:44 2015
New Revision: 243176

URL: http://llvm.org/viewvc/llvm-project?rev=243176&view=rev
Log:
COFF: Fix __ImageBase symbol relocation.

__ImageBase is a special symbol whose value is the image base address.
Previously, we handled __ImageBase symbol as an absolute symbol.

Absolute symbols point to specific locations in memory and the locations
never change even if an image is base-relocated. That means that we
don't have base relocation entries for absolute symbols.

This is not a case for __ImageBase. If an image is base-relocated, its
base address changes, and __ImageBase needs to be shifted as well.
So we have to have base relocations for __ImageBase. That means that
__ImageBase is not really an absolute symbol but a different kind of
symbol.

In this patch, I introduced a new type of symbol -- DefinedRelative.
DefinedRelative is similar to DefinedAbsolute, but it has not a VA but RVA
and is a subject of base relocation. Currently only __ImageBase is of
the new symbol type.

Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/COFF/SymbolTable.h
    lld/trunk/COFF/Symbols.cpp
    lld/trunk/COFF/Symbols.h
    lld/trunk/COFF/Writer.cpp
    lld/trunk/test/COFF/baserel.test

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Fri Jul 24 17:58:44 2015
@@ -129,14 +129,12 @@ 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, Defined *ImageBase) {
+void SectionChunk::getBaserels(std::vector<uint32_t> *Res) {
   for (const coff_relocation &Rel : Relocs) {
-    // Symbol __ImageBase is special -- it's an absolute symbol, but its
-    // address never changes even if image is relocated.
     if (!isAbs(Rel))
       continue;
     SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
-    if (Body == ImageBase)
+    if (isa<DefinedAbsolute>(Body))
       continue;
     Res->push_back(RVA + Rel.VirtualAddress);
   }
@@ -252,8 +250,7 @@ ImportThunkChunk::ImportThunkChunk(Defin
   Align = 16;
 }
 
-void ImportThunkChunk::getBaserels(std::vector<uint32_t> *Res,
-                                   Defined *ImageBase) {
+void ImportThunkChunk::getBaserels(std::vector<uint32_t> *Res) {
   if (!Config->is64())
     Res->push_back(getRVA() + 2);
 }
@@ -267,8 +264,7 @@ void ImportThunkChunk::writeTo(uint8_t *
   write32le(Buf + FileOff + 2, Operand);
 }
 
-void LocalImportChunk::getBaserels(std::vector<uint32_t> *Res,
-                                   Defined *ImageBase) {
+void LocalImportChunk::getBaserels(std::vector<uint32_t> *Res) {
   Res->push_back(getRVA());
 }
 

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Fri Jul 24 17:58:44 2015
@@ -83,7 +83,7 @@ public:
 
   // Windows-specific.
   // Collect all locations that contain absolute addresses for base relocations.
-  virtual void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) {}
+  virtual void getBaserels(std::vector<uint32_t> *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 +134,7 @@ public:
   bool hasData() const override;
   uint32_t getPermissions() const override;
   StringRef getSectionName() const override { return SectionName; }
-  void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override;
+  void getBaserels(std::vector<uint32_t> *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);
@@ -234,7 +234,7 @@ class ImportThunkChunk : public Chunk {
 public:
   explicit ImportThunkChunk(Defined *ImpSymbol);
   size_t getSize() const override { return sizeof(ImportThunkData); }
-  void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override;
+  void getBaserels(std::vector<uint32_t> *Res) override;
   void writeTo(uint8_t *Buf) override;
 
 private:
@@ -247,7 +247,7 @@ class LocalImportChunk : public Chunk {
 public:
   explicit LocalImportChunk(Defined *S) : Sym(S) {}
   size_t getSize() const override;
-  void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override;
+  void getBaserels(std::vector<uint32_t> *Res) override;
   void writeTo(uint8_t *Buf) override;
 
 private:

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

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Fri Jul 24 17:58:44 2015
@@ -602,7 +602,7 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     }
   }
 
-  Symtab.addAbsolute(mangle("__ImageBase"), Config->ImageBase);
+  Symtab.addRelative(mangle("__ImageBase"), 0);
 
   // Read as much files as we can from directives sections.
   if (auto EC = Symtab.run()) {

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Fri Jul 24 17:58:44 2015
@@ -317,8 +317,8 @@ Undefined *SymbolTable::addUndefined(Str
   return New;
 }
 
-void SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
-  addSymbol(new (Alloc) DefinedAbsolute(Name, VA));
+void SymbolTable::addRelative(StringRef Name, uint64_t VA) {
+  addSymbol(new (Alloc) DefinedRelative(Name, VA));
 }
 
 void SymbolTable::printMap(llvm::raw_ostream &OS) {

Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Fri Jul 24 17:58:44 2015
@@ -81,7 +81,7 @@ public:
 
   // Creates an Undefined symbol for a given name.
   Undefined *addUndefined(StringRef Name);
-  void addAbsolute(StringRef Name, uint64_t VA);
+  void addRelative(StringRef Name, uint64_t VA);
 
   // A list of chunks which to be added to .rdata.
   std::vector<Chunk *> LocalImportChunks;

Modified: lld/trunk/COFF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.cpp?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.cpp (original)
+++ lld/trunk/COFF/Symbols.cpp Fri Jul 24 17:58:44 2015
@@ -143,6 +143,7 @@ int SymbolBody::compare(SymbolBody *Othe
   case DefinedImportThunkKind:
   case DefinedImportDataKind:
   case DefinedAbsoluteKind:
+  case DefinedRelativeKind:
     // These all simply tie.
     return 0;
   }
@@ -178,6 +179,8 @@ uint64_t Defined::getFileOff() {
     llvm_unreachable("There is no file offset for a bitcode symbol.");
   case DefinedAbsoluteKind:
     llvm_unreachable("Cannot get a file offset for an absolute symbol.");
+  case DefinedRelativeKind:
+    llvm_unreachable("Cannot get a file offset for a relative symbol.");
   case LazyKind:
   case UndefinedKind:
     llvm_unreachable("Cannot get a file offset for an undefined symbol.");

Modified: lld/trunk/COFF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.h?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.h (original)
+++ lld/trunk/COFF/Symbols.h Fri Jul 24 17:58:44 2015
@@ -59,6 +59,7 @@ public:
     DefinedImportThunkKind,
     DefinedImportDataKind,
     DefinedAbsoluteKind,
+    DefinedRelativeKind,
     DefinedBitcodeKind,
 
     UndefinedKind,
@@ -222,6 +223,26 @@ private:
   uint64_t VA;
 };
 
+// This is a kind of absolute symbol but relative to the image base.
+// Unlike absolute symbols, relocations referring this kind of symbols
+// are subject of the base relocation. This type is used rarely --
+// mainly for __ImageBase.
+class DefinedRelative : public Defined {
+public:
+  explicit DefinedRelative(StringRef Name, uint64_t V = 0)
+      : Defined(DefinedRelativeKind, Name), RVA(V) {}
+
+  static bool classof(const SymbolBody *S) {
+    return S->kind() == DefinedRelativeKind;
+  }
+
+  uint64_t getRVA() { return RVA; }
+  void setRVA(uint64_t V) { RVA = V; }
+
+private:
+  uint64_t RVA;
+};
+
 // This class represents a symbol defined in an archive file. It is
 // created from an archive file header, and it knows how to load an
 // object file from an archive to replace itself with a defined
@@ -364,6 +385,8 @@ inline uint64_t Defined::getRVA() {
   switch (kind()) {
   case DefinedAbsoluteKind:
     return cast<DefinedAbsolute>(this)->getRVA();
+  case DefinedRelativeKind:
+    return cast<DefinedRelative>(this)->getRVA();
   case DefinedImportDataKind:
     return cast<DefinedImportData>(this)->getRVA();
   case DefinedImportThunkKind:

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Jul 24 17:58:44 2015
@@ -597,14 +597,12 @@ OutputSection *Writer::createSection(Str
 // Dest is .reloc section. Add contents to that section.
 void Writer::addBaserels(OutputSection *Dest) {
   std::vector<uint32_t> V;
-  StringRef Name = Config->is64() ? "__ImageBase" : "___ImageBase";
-  Defined *ImageBase = cast<Defined>(Symtab->find(Name)->Body);
   for (OutputSection *Sec : OutputSections) {
     if (Sec == Dest)
       continue;
     // Collect all locations for base relocations.
     for (Chunk *C : Sec->getChunks())
-      C->getBaserels(&V, ImageBase);
+      C->getBaserels(&V);
     // Add the addresses to .reloc section.
     if (!V.empty())
       addBaserelBlocks(Dest, V);

Modified: lld/trunk/test/COFF/baserel.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/baserel.test?rev=243176&r1=243175&r2=243176&view=diff
==============================================================================
--- lld/trunk/test/COFF/baserel.test (original)
+++ lld/trunk/test/COFF/baserel.test Fri Jul 24 17:58:44 2015
@@ -7,10 +7,6 @@
 # RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix=NOBASEREL
 #
 # BASEREL:      BaseReloc [
-# BASEREL-NEXT:   Entry {
-# BASEREL-NEXT:   Type: DIR64
-# BASEREL-NEXT:   Address: 0x2000
-# BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: DIR64
 # BASEREL-NEXT:   Address: 0x2007
@@ -20,20 +16,24 @@
 # BASEREL-NEXT:   Address: 0x200C
 # BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
+# BASEREL-NEXT:   Type: DIR64
+# BASEREL-NEXT:   Address: 0x201E
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: ABSOLUTE
 # BASEREL-NEXT:   Address: 0x2000
 # BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: DIR64
-# BASEREL-NEXT:   Address: 0x3000
+# BASEREL-NEXT:   Address: 0x3007
 # BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: DIR64
-# BASEREL-NEXT:   Address: 0x3007
+# BASEREL-NEXT:   Address: 0x300C
 # BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: DIR64
-# BASEREL-NEXT:   Address: 0x300C
+# BASEREL-NEXT:   Address: 0x301E
 # BASEREL-NEXT: }
 # BASEREL-NEXT: Entry {
 # BASEREL-NEXT:   Type: ABSOLUTE





More information about the llvm-commits mailing list