Fix the aarch64 logic for dynamic relocations.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 23 Feb 2016 20:19:44 +0000 (20:19 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 23 Feb 2016 20:19:44 +0000 (20:19 +0000)
There is nothing aarch64 specific in here. If a symbol can be preempted,
we need to copy the full relocation to the dynamic linker.

If a symbol cannot be preempted, we can make the dynamic linker life
easier and produce a relative relocation.

This is directly equivalent to R_X86_64_64 to R_x86_64_RELATIVE
conversion.

llvm-svn: 261678

lld/ELF/OutputSections.cpp
lld/ELF/OutputSections.h
lld/ELF/Target.cpp
lld/ELF/Writer.cpp
lld/test/ELF/aarch64-abs64-dyn.s

index 3945d88..c7fd991 100644 (file)
@@ -253,18 +253,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
 
     if (IsRela) {
       uintX_t VA = 0;
-      if (Rel.UseSymVA) {
+      if (Rel.UseSymVA)
         VA = Sym->getVA<ELFT>();
-      } else if (Rel.TargetSec) {
+      else if (Rel.TargetSec)
         VA = Rel.TargetSec->getOffset(Rel.OffsetInTargetSec) +
              Rel.TargetSec->OutSec->getVA();
-      } else if (!Sym && Rel.OffsetSec) {
-        // Sym equal to nullptr means the dynamic relocation is against a
-        // local symbol represented by Rel.SymIndex.
-        ObjectFile<ELFT> *File = Rel.OffsetSec->getFile();
-        const Elf_Sym *LocalSym = File->getLocalSymbol(Rel.SymIndex);
-        VA = getLocalTarget(*File, *LocalSym, 0);
-      }
       reinterpret_cast<Elf_Rela *>(P)->r_addend = Rel.Addend + VA;
     }
 
@@ -869,6 +862,7 @@ elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
                         const Elf_Rel_Impl<ELFT, IsRela> &RI,
                         typename ELFFile<ELFT>::uintX_t Addend) {
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
   // PPC64 has a special relocation representing the TOC base pointer
   // that does not have a corresponding symbol.
@@ -881,22 +875,10 @@ elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
   if (!Sym)
     fatal("Unsupported relocation without symbol");
 
-  return getLocalTarget(File, *Sym, Addend);
-}
-
-template <class ELFT>
-typename ELFFile<ELFT>::uintX_t
-elf2::getLocalTarget(const ObjectFile<ELFT> &File,
-                     const typename ELFFile<ELFT>::Elf_Sym &Sym,
-                     typename ELFFile<ELFT>::uintX_t Addend) {
-  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
-
-  InputSectionBase<ELFT> *Section = File.getSection(Sym);
-  if (!Section)
-    return Addend;
+  InputSectionBase<ELFT> *Section = File.getSection(*Sym);
 
-  if (Sym.getType() == STT_TLS)
-    return (Section->OutSec->getVA() + Section->getOffset(Sym) + Addend) -
+  if (Sym->getType() == STT_TLS)
+    return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) -
            Out<ELFT>::TlsPhdr->p_vaddr;
 
   // According to the ELF spec reference to a local symbol from outside
@@ -906,8 +888,8 @@ elf2::getLocalTarget(const ObjectFile<ELFT> &File,
   if (Section == &InputSection<ELFT>::Discarded || !Section->isLive())
     return Addend;
 
-  uintX_t Offset = Sym.st_value;
-  if (Sym.getType() == STT_SECTION) {
+  uintX_t Offset = Sym->st_value;
+  if (Sym->getType() == STT_SECTION) {
     Offset += Addend;
     Addend = 0;
   }
@@ -1665,18 +1647,5 @@ template uint64_t getLocalRelTarget(const ObjectFile<ELF64LE> &,
 template uint64_t getLocalRelTarget(const ObjectFile<ELF64BE> &,
                                     const ELFFile<ELF64BE>::Elf_Rela &,
                                     uint64_t);
-
-template uint32_t getLocalTarget(const ObjectFile<ELF32LE> &,
-                                 const ELFFile<ELF32LE>::Elf_Sym &Sym,
-                                 uint32_t);
-template uint32_t getLocalTarget(const ObjectFile<ELF32BE> &,
-                                 const ELFFile<ELF32BE>::Elf_Sym &Sym,
-                                 uint32_t);
-template uint64_t getLocalTarget(const ObjectFile<ELF64LE> &,
-                                 const ELFFile<ELF64LE>::Elf_Sym &Sym,
-                                 uint64_t);
-template uint64_t getLocalTarget(const ObjectFile<ELF64BE> &,
-                                 const ELFFile<ELF64BE>::Elf_Sym &Sym,
-                                 uint64_t);
 }
 }
index 8b0b54d..a3a80db 100644 (file)
@@ -53,12 +53,6 @@ getLocalRelTarget(const ObjectFile<ELFT> &File,
                   const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
                   typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
 
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t
-getLocalTarget(const ObjectFile<ELFT> &File,
-               const typename llvm::object::ELFFile<ELFT>::Elf_Sym &Sym,
-               typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
-
 bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
 
 // This represents a section in an output file.
@@ -193,7 +187,6 @@ template <class ELFT> struct DynamicReloc {
   } OKind;
 
   SymbolBody *Sym = nullptr;
-  uint32_t SymIndex = 0;
   InputSectionBase<ELFT> *OffsetSec = nullptr;
   uintX_t OffsetInSec = 0;
   bool UseSymVA = false;
@@ -214,12 +207,6 @@ template <class ELFT> struct DynamicReloc {
         OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {}
 
   DynamicReloc(uint32_t Type, InputSectionBase<ELFT> *OffsetSec,
-               uintX_t OffsetInSec, bool UseSymVA, uint32_t SymIndex,
-               uintX_t Addend)
-      : Type(Type), OKind(Off_Sec), SymIndex(SymIndex), OffsetSec(OffsetSec),
-        OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {}
-
-  DynamicReloc(uint32_t Type, InputSectionBase<ELFT> *OffsetSec,
                uintX_t OffsetInSec, InputSectionBase<ELFT> *TargetSec,
                uintX_t OffsetInTargetSec, uintX_t Addend)
       : Type(Type), OKind(Off_Sec), OffsetSec(OffsetSec),
@@ -267,7 +254,6 @@ private:
 
 template <class ELFT>
 class RelocationSection final : public OutputSectionBase<ELFT> {
-  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
index 01baba9..a2a609c 100644 (file)
@@ -181,8 +181,8 @@ public:
                 int32_t Index, unsigned RelOff) const override;
   unsigned getTlsGotRel(unsigned Type) const override;
   bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;
+  bool isRelRelative(uint32_t Type) const override;
   bool needsCopyRelImpl(uint32_t Type) const override;
-  bool needsDynRelative(unsigned Type) const override;
   bool needsGot(uint32_t Type, SymbolBody &S) const override;
   PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
@@ -1209,6 +1209,8 @@ AArch64TargetInfo::AArch64TargetInfo() {
   PltZeroSize = 32;
 }
 
+bool AArch64TargetInfo::isRelRelative(uint32_t Type) const { return false; }
+
 bool AArch64TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
   return Type == R_AARCH64_TLSDESC_ADR_PAGE21 ||
          Type == R_AARCH64_TLSDESC_LD64_LO12_NC ||
@@ -1305,10 +1307,6 @@ bool AArch64TargetInfo::needsCopyRelImpl(uint32_t Type) const {
   }
 }
 
-bool AArch64TargetInfo::needsDynRelative(unsigned Type) const {
-  return Config->Shared && Type == R_AARCH64_ABS64;
-}
-
 bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
   switch (Type) {
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
index ab844d3..0f7edf8 100644 (file)
@@ -311,16 +311,9 @@ void Writer<ELFT>::scanRelocs(
     if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
       continue;
 
-    if (Target->needsDynRelative(Type)) {
-      // If Body is null it means the relocation is against a local symbol
-      // and thus we need to pass the local symbol index instead.
-      if (Body)
-        Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true,
-                                      Body, getAddend<ELFT>(RI)});
-      else
-        Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, false,
-                                      SymIndex, getAddend<ELFT>(RI)});
-    }
+    if (Target->needsDynRelative(Type))
+      Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true,
+                                    Body, getAddend<ELFT>(RI)});
 
     // MIPS has a special rule to create GOTs for local symbols.
     if (Config->EMachine == EM_MIPS && !canBePreempted(Body, true) &&
index f9605ef..d1242c2 100644 (file)
@@ -1,21 +1,27 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
 
-// Creates a R_AARCH64_ABS64 relocation against _foo. It will be used on a
-// shared object to check for a dynamic relocation creation.
-.globl _foo
-_foo:
-   ret
-_foo_init_array:
-  .xword _foo
+// Creates a R_AARCH64_ABS64 relocation against foo and bar
+        .globl foo
+foo:
+
+        .global bar
+        .hidden bar
+bar:
+
+        .data
+        .xword foo
+        .xword bar
 
 // RUN: ld.lld -shared -o %t.so %t.o
 // RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s
 
-// CHECK:       Dynamic Relocations {
-// CHECK-NEXT:      {{.*}} R_AARCH64_RELATIVE - [[FOO_ADDR:[0-9xa-f]+]]
+// CHECK:      Dynamic Relocations {
+// CHECK-NEXT:   {{.*}} R_AARCH64_ABS64 foo 0x0
+// CHECK-NEXT:   {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]]
+// CHECK-NEXT: }
 
-// CHECK:       Symbols [
-// CHECK:         Symbol {
-// CHECK:           Name: _foo
-// CHECK:           Value: [[FOO_ADDR]]
+// CHECK:      Symbols [
+// CHECK:        Symbol {
+// CHECK:          Name: bar
+// CHECK-NEXT:     Value: [[BAR_ADDR]]