[lld] r261760 - Move target independent code out of x86_64 only path.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 24 10:24:24 PST 2016


Author: rafael
Date: Wed Feb 24 12:24:23 2016
New Revision: 261760

URL: http://llvm.org/viewvc/llvm-project?rev=261760&view=rev
Log:
Move target independent code out of x86_64 only path.

The logic for deciding if an undefined symbol should have the value of a
got entry is not target specific.

Added:
    lld/trunk/test/ELF/undef-with-plt-addr-i686.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s
    lld/trunk/test/ELF/shared.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Feb 24 12:24:23 2016
@@ -217,7 +217,7 @@ void InputSectionBase<ELFT>::relocate(ui
     }
 
     uintX_t SymVA = Body->getVA<ELFT>();
-    if (Target->needsPlt(Type, *Body)) {
+    if (Target->needsPlt<ELFT>(Type, *Body)) {
       SymVA = Body->getPltVA<ELFT>();
     } else if (Target->needsGot(Type, *Body)) {
       if (Config->EMachine == EM_MIPS && !canBePreempted(Body, true))

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Feb 24 12:24:23 2016
@@ -93,7 +93,7 @@ public:
   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;
+  bool needsPltImpl(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
@@ -101,6 +101,7 @@ public:
   unsigned relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                     uint64_t SA, const SymbolBody *S) const override;
   bool isGotRelative(uint32_t Type) const override;
+  bool refersToGotEntry(uint32_t Type) const override;
 
 private:
   void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
@@ -127,7 +128,8 @@ public:
                 int32_t Index, unsigned RelOff) const override;
   bool needsCopyRelImpl(uint32_t Type) const override;
   bool needsGot(uint32_t Type, SymbolBody &S) const override;
-  PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override;
+  bool refersToGotEntry(uint32_t Type) const override;
+  bool needsPltImpl(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
@@ -163,7 +165,7 @@ public:
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
   bool needsGot(uint32_t Type, SymbolBody &S) const override;
-  PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override;
+  bool needsPltImpl(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
@@ -184,7 +186,7 @@ public:
   bool isRelRelative(uint32_t Type) const override;
   bool needsCopyRelImpl(uint32_t Type) const override;
   bool needsGot(uint32_t Type, SymbolBody &S) const override;
-  PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override;
+  bool needsPltImpl(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
@@ -220,7 +222,7 @@ public:
   void writeGotHeader(uint8_t *Buf) const override;
   bool needsCopyRelImpl(uint32_t Type) const override;
   bool needsGot(uint32_t Type, SymbolBody &S) const override;
-  PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override;
+  bool needsPltImpl(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t S, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
@@ -291,8 +293,43 @@ bool TargetInfo::isSizeRel(uint32_t Type
 
 bool TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { return false; }
 
+bool TargetInfo::needsPltImpl(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
+
+bool TargetInfo::refersToGotEntry(uint32_t Type) const { return false; }
+
+template <class ELFT>
 TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type,
                                          const SymbolBody &S) const {
+  if (needsPltImpl(Type, S))
+    return Plt_Explicit;
+
+  // This handles a non PIC program call to function in a shared library.
+  // In an ideal world, we could just report an error saying the relocation
+  // can overflow at runtime.
+  // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
+  // libc.so.
+  //
+  // The general idea on how to handle such cases is to create a PLT entry
+  // and use that as the function value.
+  //
+  // For the static linking part, we just return true and everything else
+  // will use the the PLT entry as the address.
+  //
+  // The remaining problem is making sure pointer equality still works. We
+  // need the help of the dynamic linker for that. We let it know that we have
+  // a direct reference to a so symbol by creating an undefined symbol with a
+  // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
+  // the value of the symbol we created. This is true even for got entries, so
+  // pointer equality is maintained. To avoid an infinite loop, the only entry
+  // that points to the real function is a dedicated got entry used by the
+  // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
+  // R_386_JMP_SLOT, etc).
+  if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(&S))
+    if (SS->Sym.getType() == STT_FUNC && !refersToGotEntry(Type))
+      return Plt_Implicit;
+
   return Plt_No;
 }
 
@@ -417,16 +454,14 @@ bool X86TargetInfo::needsGot(uint32_t Ty
     return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
   if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
     return !canRelaxTls(Type, &S);
-  return Type == R_386_GOT32 || needsPlt(Type, S);
+  return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
 }
 
-TargetInfo::PltNeed X86TargetInfo::needsPlt(uint32_t Type,
-                                            const SymbolBody &S) const {
+bool X86TargetInfo::needsPltImpl(uint32_t Type, const SymbolBody &S) const {
   if (isGnuIFunc<ELF32LE>(S) ||
-      (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
-      (Type == R_386_PC32 && S.isShared()))
-    return Plt_Explicit;
-  return Plt_No;
+      (Type == R_386_PLT32 && canBePreempted(&S, true)))
+    return true;
+  return false;
 }
 
 bool X86TargetInfo::isGotRelative(uint32_t Type) const {
@@ -436,6 +471,10 @@ bool X86TargetInfo::isGotRelative(uint32
   return Type == R_386_GOTOFF;
 }
 
+bool X86TargetInfo::refersToGotEntry(uint32_t Type) const {
+  return Type == R_386_GOT32;
+}
+
 void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                                 uint64_t P, uint64_t SA, uint64_t ZA,
                                 uint8_t *PairedLoc) const {
@@ -680,12 +719,16 @@ bool X86_64TargetInfo::needsCopyRelImpl(
          Type == R_X86_64_64;
 }
 
+bool X86_64TargetInfo::refersToGotEntry(uint32_t Type) const {
+  return Type == R_X86_64_GOTPCREL;
+}
+
 bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
   if (Type == R_X86_64_TLSGD)
     return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
   if (Type == R_X86_64_GOTTPOFF)
     return !canRelaxTls(Type, &S);
-  return Type == R_X86_64_GOTPCREL || needsPlt(Type, S);
+  return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
 }
 
 unsigned X86_64TargetInfo::getTlsGotRel(unsigned Type) const {
@@ -707,52 +750,19 @@ bool X86_64TargetInfo::isTlsDynRel(unsig
   return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
 }
 
-TargetInfo::PltNeed X86_64TargetInfo::needsPlt(uint32_t Type,
-                                               const SymbolBody &S) const {
+bool X86_64TargetInfo::needsPltImpl(uint32_t Type, const SymbolBody &S) const {
   if (needsCopyRel<ELF64LE>(Type, S))
-    return Plt_No;
+    return false;
   if (isGnuIFunc<ELF64LE>(S))
-    return Plt_Explicit;
+    return true;
 
   switch (Type) {
   default:
     return Plt_No;
-  case R_X86_64_32:
-  case R_X86_64_32S:
-  case R_X86_64_64:
-  case R_X86_64_PC32:
-    // This relocation is defined to have a value of (S + A - P).
-    // The problems start when a non PIC program calls a function in a shared
-    // library.
-    // In an ideal world, we could just report an error saying the relocation
-    // can overflow at runtime.
-    // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
-    // libc.so.
-    //
-    // The general idea on how to handle such cases is to create a PLT entry
-    // and use that as the function value.
-    //
-    // For the static linking part, we just return true and everything else
-    // will use the the PLT entry as the address.
-    //
-    // The remaining problem is making sure pointer equality still works. We
-    // need the help of the dynamic linker for that. We let it know that we have
-    // a direct reference to a so symbol by creating an undefined symbol with a
-    // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
-    // the value of the symbol we created. This is true even for got entries, so
-    // pointer equality is maintained. To avoid an infinite loop, the only entry
-    // that points to the real function is a dedicated got entry used by the
-    // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
-    // R_386_JMP_SLOT, etc).
-    if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S)) {
-      if (SS->Sym.getType() == STT_FUNC)
-        return Plt_Implicit;
-    }
-    return Plt_No;
   case R_X86_64_PLT32:
     if (canBePreempted(&S, true))
-      return Plt_Explicit;
-    return Plt_No;
+      return true;
+    return false;
   }
 }
 
@@ -1044,7 +1054,7 @@ void PPC64TargetInfo::writePlt(uint8_t *
 }
 
 bool PPC64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
-  if (needsPlt(Type, S))
+  if (needsPlt<ELF64BE>(Type, S))
     return true;
 
   switch (Type) {
@@ -1059,12 +1069,11 @@ bool PPC64TargetInfo::needsGot(uint32_t
   }
 }
 
-TargetInfo::PltNeed PPC64TargetInfo::needsPlt(uint32_t Type,
-                                              const SymbolBody &S) const {
+bool PPC64TargetInfo::needsPltImpl(uint32_t Type, const SymbolBody &S) const {
   // These are function calls that need to be redirected through a PLT stub.
   if (Type == R_PPC64_REL24 && canBePreempted(&S, false))
-    return Plt_Explicit;
-  return Plt_No;
+    return true;
+  return false;
 }
 
 bool PPC64TargetInfo::isRelRelative(uint32_t Type) const {
@@ -1318,24 +1327,23 @@ bool AArch64TargetInfo::needsGot(uint32_
   case R_AARCH64_LD64_GOT_LO12_NC:
     return true;
   default:
-    return needsPlt(Type, S);
+    return needsPlt<ELF64LE>(Type, S);
   }
 }
 
-TargetInfo::PltNeed AArch64TargetInfo::needsPlt(uint32_t Type,
-                                                const SymbolBody &S) const {
+bool AArch64TargetInfo::needsPltImpl(uint32_t Type, const SymbolBody &S) const {
   if (isGnuIFunc<ELF64LE>(S))
-    return Plt_Explicit;
+    return true;
   switch (Type) {
   default:
-    return Plt_No;
+    return false;
   case R_AARCH64_CALL26:
   case R_AARCH64_CONDBR19:
   case R_AARCH64_JUMP26:
   case R_AARCH64_TSTBR14:
     if (canBePreempted(&S, true))
-      return Plt_Explicit;
-    return Plt_No;
+      return true;
+    return false;
   }
 }
 
@@ -1693,20 +1701,21 @@ bool MipsTargetInfo<ELFT>::needsCopyRelI
 
 template <class ELFT>
 bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, SymbolBody &S) const {
-  return needsPlt(Type, S) || Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
+  return needsPlt<ELFT>(Type, S) || Type == R_MIPS_GOT16 ||
+         Type == R_MIPS_CALL16;
 }
 
 template <class ELFT>
-TargetInfo::PltNeed MipsTargetInfo<ELFT>::needsPlt(uint32_t Type,
-                                                   const SymbolBody &S) const {
+bool MipsTargetInfo<ELFT>::needsPltImpl(uint32_t Type,
+                                        const SymbolBody &S) const {
   if (needsCopyRel<ELFT>(Type, S))
-    return Plt_No;
+    return false;
   if (Type == R_MIPS_26 && canBePreempted(&S, false))
-    return Plt_Explicit;
+    return true;
   if (Type == R_MIPS_HI16 || Type == R_MIPS_LO16 || isRelRelative(Type))
     if (S.isShared())
-      return Plt_Explicit;
-  return Plt_No;
+      return true;
+  return false;
 }
 
 template <class ELFT>
@@ -1853,5 +1862,14 @@ template bool TargetInfo::needsCopyRel<E
                                                 const SymbolBody &) const;
 template bool TargetInfo::needsCopyRel<ELF64BE>(uint32_t,
                                                 const SymbolBody &) const;
+
+template TargetInfo::PltNeed
+TargetInfo::needsPlt<ELF32LE>(uint32_t, const SymbolBody &) const;
+template TargetInfo::PltNeed
+TargetInfo::needsPlt<ELF32BE>(uint32_t, const SymbolBody &) const;
+template TargetInfo::PltNeed
+TargetInfo::needsPlt<ELF64LE>(uint32_t, const SymbolBody &) const;
+template TargetInfo::PltNeed
+TargetInfo::needsPlt<ELF64BE>(uint32_t, const SymbolBody &) const;
 }
 }

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Feb 24 12:24:23 2016
@@ -55,9 +55,12 @@ public:
   virtual bool isSizeRel(uint32_t Type) const;
   virtual bool needsDynRelative(unsigned Type) const { return false; }
   virtual bool needsGot(uint32_t Type, SymbolBody &S) const;
+  virtual bool refersToGotEntry(uint32_t Type) const;
 
   enum PltNeed { Plt_No, Plt_Explicit, Plt_Implicit };
-  virtual PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const;
+  template <class ELFT>
+  PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const;
+
   virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                            uint64_t P, uint64_t SA, uint64_t ZA = 0,
                            uint8_t *PairedLoc = nullptr) const = 0;
@@ -95,6 +98,7 @@ public:
 
 private:
   virtual bool needsCopyRelImpl(uint32_t Type) const;
+  virtual bool needsPltImpl(uint32_t Type, const SymbolBody &S) const;
 };
 
 uint64_t getPPC64TocBase();

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Feb 24 12:24:23 2016
@@ -362,7 +362,7 @@ void Writer<ELFT>::scanRelocs(
     // for the symbol.
     TargetInfo::PltNeed NeedPlt = TargetInfo::Plt_No;
     if (Body)
-      NeedPlt = Target->needsPlt(Type, *Body);
+      NeedPlt = Target->needsPlt<ELFT>(Type, *Body);
     if (NeedPlt) {
       if (NeedPlt == TargetInfo::Plt_Implicit)
         Body->NeedsCopyOrPltAddr = true;

Modified: lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s (original)
+++ lld/trunk/test/ELF/Inputs/undef-with-plt-addr.s Wed Feb 24 12:24:23 2016
@@ -1,4 +1,3 @@
 	.globl	set_data
 	.type	set_data, at function
 set_data:
-	retq

Modified: lld/trunk/test/ELF/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/shared.s?rev=261760&r1=261759&r2=261760&view=diff
==============================================================================
--- lld/trunk/test/ELF/shared.s (original)
+++ lld/trunk/test/ELF/shared.s Wed Feb 24 12:24:23 2016
@@ -291,5 +291,5 @@
 
 .global _start
 _start:
-.long bar
-.long zed
+.long bar at GOT
+.long zed at GOT

Added: lld/trunk/test/ELF/undef-with-plt-addr-i686.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/undef-with-plt-addr-i686.s?rev=261760&view=auto
==============================================================================
--- lld/trunk/test/ELF/undef-with-plt-addr-i686.s (added)
+++ lld/trunk/test/ELF/undef-with-plt-addr-i686.s Wed Feb 24 12:24:23 2016
@@ -0,0 +1,23 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t3
+// RUN: llvm-readobj -t -s %t3 | FileCheck %s
+
+.globl _start
+_start:
+mov $set_data, %eax
+
+// Test that set_data has an address in the .plt
+
+// CHECK:      Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT:   SHF_ALLOC
+// CHECK-NEXT:   SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11010
+
+// CHECK:      Name:    set_data
+// CHECK-NEXT: Value:   0x11020




More information about the llvm-commits mailing list