[lld] r251526 - [ELF2] R_X86_64_COPY relocation implemented

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 28 09:48:59 PDT 2015


Author: grimar
Date: Wed Oct 28 11:48:58 2015
New Revision: 251526

URL: http://llvm.org/viewvc/llvm-project?rev=251526&view=rev
Log:
[ELF2] R_X86_64_COPY relocation implemented

Differential revision: http://reviews.llvm.org/D14090.

Added:
    lld/trunk/test/elf2/Inputs/relocation-copy.s
    lld/trunk/test/elf2/relocation-copy.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Oct 28 11:48:58 2015
@@ -112,7 +112,8 @@ void InputSection<ELFT>::relocate(
     } else if (Target->relocPointsToGot(Type)) {
       SymVA = Out<ELFT>::Got->getVA();
       Type = Target->getPCRelReloc();
-    } else if (isa<SharedSymbol<ELFT>>(Body)) {
+    } else if (!Target->relocNeedsCopy(Type, Body) &&
+               isa<SharedSymbol<ELFT>>(Body)) {
       continue;
     }
     Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, BaseAddr + RI.r_offset,

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Oct 28 11:48:58 2015
@@ -163,6 +163,7 @@ template <class ELFT> void RelocationSec
       Body = Body->repl();
 
     uint32_t Type = RI.getType(Config->Mips64EL);
+    bool NeedsCopy = Body && Target->relocNeedsCopy(Type, *Body);
     bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
     bool CanBePreempted = canBePreempted(Body, NeedsGot);
     bool LazyReloc = Body && Target->supportsLazyRelocations() &&
@@ -175,7 +176,8 @@ template <class ELFT> void RelocationSec
                                       : Target->getGotReloc(),
                             Config->Mips64EL);
       else
-        P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type,
+        P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
+                            NeedsCopy ? Target->getCopyReloc() : Type,
                             Config->Mips64EL);
     } else {
       P->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
@@ -186,6 +188,9 @@ template <class ELFT> void RelocationSec
         P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
       else
         P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+    } else if (NeedsCopy) {
+      P->r_offset = Out<ELFT>::Bss->getVA() +
+                    dyn_cast<SharedSymbol<ELFT>>(Body)->OffsetInBSS;
     } else {
       P->r_offset = RI.r_offset + C.OutSec->getVA() + C.OutSecOff;
     }
@@ -195,7 +200,9 @@ template <class ELFT> void RelocationSec
       OrigAddend = static_cast<const Elf_Rela &>(RI).r_addend;
 
     uintX_t Addend;
-    if (CanBePreempted)
+    if (NeedsCopy)
+      Addend = 0;
+    else if (CanBePreempted)
       Addend = OrigAddend;
     else if (Body)
       Addend = getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body)) + OrigAddend;
@@ -637,7 +644,12 @@ typename ELFFile<ELFT>::uintX_t lld::elf
   }
   case SymbolBody::DefinedCommonKind:
     return Out<ELFT>::Bss->getVA() + cast<DefinedCommon<ELFT>>(S).OffsetInBSS;
-  case SymbolBody::SharedKind:
+  case SymbolBody::SharedKind: {
+    auto &SS = cast<SharedSymbol<ELFT>>(S);
+    if (SS.NeedsCopy)
+      return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS;
+    return 0;
+  }
   case SymbolBody::UndefinedKind:
     return 0;
   case SymbolBody::LazyKind:
@@ -990,9 +1002,13 @@ void SymbolTableSection<ELFT>::writeGlob
     case SymbolBody::DefinedCommonKind:
       OutSec = Out<ELFT>::Bss;
       break;
+    case SymbolBody::SharedKind: {
+      if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)
+        OutSec = Out<ELFT>::Bss;
+      break;
+    }
     case SymbolBody::UndefinedKind:
     case SymbolBody::DefinedAbsoluteKind:
-    case SymbolBody::SharedKind:
     case SymbolBody::LazyKind:
       break;
     }

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Wed Oct 28 11:48:58 2015
@@ -271,6 +271,7 @@ typename Undefined<ELFT>::Elf_Sym Undefi
 template <class ELFT> class SharedSymbol : public Defined<ELFT> {
   typedef Defined<ELFT> Base;
   typedef typename Base::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
   static bool classof(const SymbolBody *S) {
@@ -281,6 +282,10 @@ public:
       : Defined<ELFT>(Base::SharedKind, Name, Sym), File(F) {}
 
   SharedFile<ELFT> *File;
+
+  // Can have offset if requires copy relocation.
+  uintX_t OffsetInBSS = 0;
+  bool NeedsCopy = false;
 };
 
 // This class represents a symbol defined in an archive file. It is

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Oct 28 11:48:58 2015
@@ -68,6 +68,7 @@ public:
                          uint64_t PltEntryAddr) const override;
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr, int32_t Index) const override;
+  bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const override;
   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
@@ -144,6 +145,10 @@ TargetInfo *createTarget() {
 
 TargetInfo::~TargetInfo() {}
 
+bool TargetInfo::relocNeedsCopy(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
+
 unsigned TargetInfo::getPLTRefReloc(unsigned Type) const { return PCRelReloc; }
 
 bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; }
@@ -200,6 +205,7 @@ void X86TargetInfo::relocateOne(uint8_t
 }
 
 X86_64TargetInfo::X86_64TargetInfo() {
+  CopyReloc = R_X86_64_COPY;
   PCRelReloc = R_X86_64_PC32;
   GotReloc = R_X86_64_GLOB_DAT;
   GotRefReloc = R_X86_64_PC32;
@@ -242,6 +248,15 @@ void X86_64TargetInfo::writePltEntry(uin
   write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
 }
 
+bool X86_64TargetInfo::relocNeedsCopy(uint32_t Type,
+                                      const SymbolBody &S) const {
+  if (Type == R_X86_64_32S || Type == R_X86_64_32 || Type == R_X86_64_PC32 ||
+      Type == R_X86_64_64)
+    if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
+      return SS->Sym.getType() == STT_OBJECT;
+  return false;
+}
+
 bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
   return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
 }
@@ -258,6 +273,9 @@ unsigned X86_64TargetInfo::getPLTRefRelo
 }
 
 bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+  if (relocNeedsCopy(Type, S))
+    return false;
+
   switch (Type) {
   default:
     return false;

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Oct 28 11:48:58 2015
@@ -22,6 +22,7 @@ class TargetInfo {
 public:
   unsigned getPageSize() const { return PageSize; }
   uint64_t getVAStart() const { return VAStart; }
+  unsigned getCopyReloc() const { return CopyReloc; }
   unsigned getPCRelReloc() const { return PCRelReloc; }
   unsigned getGotReloc() const { return GotReloc; }
   unsigned getPltReloc() const { return PltReloc; }
@@ -37,6 +38,7 @@ public:
   virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                              uint64_t PltEntryAddr, int32_t Index) const = 0;
   virtual bool isRelRelative(uint32_t Type) const;
+  virtual bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const;
   virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
   virtual bool relocPointsToGot(uint32_t Type) const;
   virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
@@ -56,6 +58,7 @@ protected:
   // 0x200000, but it looks like every OS uses 4k pages for executables.
   uint64_t VAStart = 0x10000;
 
+  unsigned CopyReloc;
   unsigned PCRelReloc;
   unsigned GotRefReloc;
   unsigned GotReloc;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Oct 28 11:48:58 2015
@@ -200,6 +200,11 @@ void Writer<ELFT>::scanRelocs(
     bool NeedsGot = false;
     bool NeedsPlt = false;
     if (Body) {
+      if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
+        if (E->NeedsCopy)
+          continue;
+        E->NeedsCopy = Target->relocNeedsCopy(Type, *Body);
+      }
       NeedsPlt = Target->relocNeedsPlt(Type, *Body);
       if (NeedsPlt) {
         if (Body->isInPlt())
@@ -395,6 +400,24 @@ static void addCommonSymbols(std::vector
   Out<ELFT>::Bss->setSize(Off);
 }
 
+template <class ELFT>
+static void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+  typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
+  uintX_t Off = Out<ELFT>::Bss->getSize();
+  for (SharedSymbol<ELFT> *C : Syms) {
+    const Elf_Sym &Sym = C->Sym;
+    // We don't know the exact alignment requirement for the data copied by a
+    // copy relocation, so align that to 16 byte boundaries that should be large
+    // enough unconditionally.
+    Off = RoundUpToAlignment(Off, 16);
+    C->OffsetInBSS = Off;
+    Off += Sym.st_size;
+  }
+  Out<ELFT>::Bss->setSize(Off);
+}
+
 static StringRef getOutputName(StringRef S) {
   if (S.startswith(".text."))
     return ".text";
@@ -498,6 +521,7 @@ template <class ELFT> void Writer<ELFT>:
             scanRelocs(*S);
 
   std::vector<DefinedCommon<ELFT> *> CommonSymbols;
+  std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
   for (auto &P : Symtab.getSymbols()) {
     SymbolBody *Body = P.second->Body;
     if (auto *U = dyn_cast<Undefined<ELFT>>(Body))
@@ -506,6 +530,10 @@ template <class ELFT> void Writer<ELFT>:
 
     if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
       CommonSymbols.push_back(C);
+    if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
+      if (SC->NeedsCopy)
+        SharedCopySymbols.push_back(SC);
+
     if (!includeInSymtab<ELFT>(*Body))
       continue;
     if (Out<ELFT>::SymTab)
@@ -515,6 +543,7 @@ template <class ELFT> void Writer<ELFT>:
       Out<ELFT>::DynSymTab->addSymbol(Body);
   }
   addCommonSymbols(CommonSymbols);
+  addSharedCopySymbols(SharedCopySymbols);
 
   // This order is not the same as the final output order
   // because we sort the sections using their attributes below.

Added: lld/trunk/test/elf2/Inputs/relocation-copy.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/relocation-copy.s?rev=251526&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/relocation-copy.s (added)
+++ lld/trunk/test/elf2/Inputs/relocation-copy.s Wed Oct 28 11:48:58 2015
@@ -0,0 +1,14 @@
+.text
+.type x, at object
+.bss
+.globl x
+.align 4
+x:
+.long 0
+.size x, 4
+.type y, at object
+.globl y
+.align 4
+y:
+.long 0
+.size y, 4

Added: lld/trunk/test/elf2/relocation-copy.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation-copy.s?rev=251526&view=auto
==============================================================================
--- lld/trunk/test/elf2/relocation-copy.s (added)
+++ lld/trunk/test/elf2/relocation-copy.s Wed Oct 28 11:48:58 2015
@@ -0,0 +1,52 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
+// RUN: ld.lld2 -shared %t2.o -o %t.so
+// RUN: ld.lld2 -e main %t.o %t.so -o %t3
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -r --expand-relocs %t3 | FileCheck %s
+// RUN: llvm-objdump -r -d %t3 | FileCheck -check-prefix=CODE %s
+
+.text
+.globl main
+.align 16, 0x90
+.type main, at function
+main:
+movl $5, x
+movl $7, y
+
+// CHECK:      Name: .bss
+// CHECK-NEXT:  Type: SHT_NOBITS (0x8)
+// CHECK-NEXT:  Flags [ (0x3)
+// CHECK-NEXT:   SHF_ALLOC (0x2)
+// CHECK-NEXT:   SHF_WRITE (0x1)
+// CHECK-NEXT:  ]
+// CHECK-NEXT:  Address: 0x120A0
+// CHECK-NEXT:  Offset: 0x20A0
+// CHECK-NEXT:  Size: 20
+// CHECK-NEXT:  Link: 0
+// CHECK-NEXT:  Info: 0
+// CHECK-NEXT:  AddressAlignment: 4
+// CHECK-NEXT:  EntrySize: 0
+
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT:     Relocation {
+// CHECK-NEXT:       Offset:
+// CHECK-NEXT:       Type: R_X86_64_COPY
+// CHECK-NEXT:       Symbol: x
+// CHECK-NEXT:       Addend: 0x0
+// CHECK-NEXT:     }
+// CHECK-NEXT:     Relocation {
+// CHECK-NEXT:       Offset:
+// CHECK-NEXT:       Type: R_X86_64_COPY
+// CHECK-NEXT:       Symbol: y
+// CHECK-NEXT:       Addend: 0x0
+// CHECK-NEXT:     }
+
+// 73888 = 0x120A0
+// 16 is alignment here
+// 73892 = 0x120A0 + 16
+// CODE: Disassembly of section .text:
+// CODE-NEXT: main:
+// CODE-NEXT: 11000: c7 04 25 a0 20 01 00 05 00 00 00 movl $5, 73888
+// CODE-NEXT: 1100b: c7 04 25 b0 20 01 00 07 00 00 00 movl $7, 73904




More information about the llvm-commits mailing list