[lld] r256143 - [ELF] - R_386_GOTOFF relocation implemented.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 21 02:00:13 PST 2015


Author: grimar
Date: Mon Dec 21 04:00:12 2015
New Revision: 256143

URL: http://llvm.org/viewvc/llvm-project?rev=256143&view=rev
Log:
[ELF] - R_386_GOTOFF relocation implemented.

R_386_GOTOFF is calculated as S + A - GOT, where:
S - Represents the value of the symbol whose index resides in the relocation entry.
A - Represents the addend used to compute the value of the relocatable field.
GOT - Represents the address of the global offset table.

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

Added:
    lld/trunk/test/ELF/got-i386.s
Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Dec 21 04:00:12 2015
@@ -21,6 +21,8 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf2;
 
+bool lld::elf2::HasGotOffRel = false;
+
 template <class ELFT>
 OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
                                            uintX_t sh_flags)

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Dec 21 04:00:12 2015
@@ -37,6 +37,10 @@ template <class ELFT> class ObjectFile;
 template <class ELFT> class DefinedRegular;
 template <class ELFT> class ELFSymbolBody;
 
+// Flag to force GOT to be in output if we have relocations
+// that relies on its address.
+extern bool HasGotOffRel;
+
 template <class ELFT>
 static inline typename llvm::object::ELFFile<ELFT>::uintX_t
 getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Dec 21 04:00:12 2015
@@ -95,6 +95,7 @@ public:
   unsigned relocateTlsOptimize(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;
 
 private:
   void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
@@ -232,6 +233,8 @@ bool TargetInfo::needsCopyRel(uint32_t T
   return false;
 }
 
+bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
+
 unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; }
 
 bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
@@ -358,6 +361,13 @@ bool X86TargetInfo::relocNeedsPlt(uint32
          (Type == R_386_PC32 && S.isShared());
 }
 
+bool X86TargetInfo::isGotRelative(uint32_t Type) const {
+  // This relocation does not require got entry,
+  // but it is relative to got and needs it to be created.
+  // Here we request for that.
+  return Type == R_386_GOTOFF;
+}
+
 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 {
@@ -366,6 +376,7 @@ void X86TargetInfo::relocateOne(uint8_t
     add32le(Loc, SA);
     break;
   case R_386_GOT32:
+  case R_386_GOTOFF:
     add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
     break;
   case R_386_GOTPC:

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Mon Dec 21 04:00:12 2015
@@ -64,6 +64,7 @@ public:
   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;
+  virtual bool isGotRelative(uint32_t Type) const;
   virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const;
   virtual bool needsCopyRel(uint32_t Type, const SymbolBody &S) const;
   virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Dec 21 04:00:12 2015
@@ -209,6 +209,9 @@ void Writer<ELFT>::scanRelocs(
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     uint32_t Type = RI.getType(Config->Mips64EL);
 
+    if (Target->isGotRelative(Type))
+      HasGotOffRel = true;
+
     if (Target->isTlsLocalDynamicReloc(Type)) {
       if (Target->isTlsOptimized(Type, nullptr))
         continue;
@@ -774,10 +777,17 @@ template <class ELFT> void Writer<ELFT>:
     }
   }
 
+  bool needsGot = !Out<ELFT>::Got->empty();
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
-  if (!Out<ELFT>::Got->empty() ||
-      (isOutputDynamic() && Config->EMachine == EM_MIPS))
+  if (Config->EMachine == EM_MIPS)
+    needsGot |= isOutputDynamic();
+  // If we have a relocation that is relative to GOT (such as GOTOFFREL),
+  // we need to emit a GOT even if it's empty.
+  if (HasGotOffRel)
+    needsGot = true;
+
+  if (needsGot)
     OutputSections.push_back(Out<ELFT>::Got);
   if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
     OutputSections.push_back(Out<ELFT>::GotPlt);

Added: lld/trunk/test/ELF/got-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/got-i386.s?rev=256143&view=auto
==============================================================================
--- lld/trunk/test/ELF/got-i386.s (added)
+++ lld/trunk/test/ELF/got-i386.s Mon Dec 21 04:00:12 2015
@@ -0,0 +1,56 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s -r -t %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+// REQUIRES: x86
+
+// CHECK:      Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT:   SHF_ALLOC
+// CHECK-NEXT:   SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+
+// CHECK:      Symbol {
+// CHECK:       Name: bar
+// CHECK-NEXT:  Value: 0x12000
+// CHECK-NEXT:  Size: 10
+// CHECK-NEXT:  Binding: Global
+// CHECK-NEXT:  Type: Object
+// CHECK-NEXT:  Other: 0
+// CHECK-NEXT:  Section: .bss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:  Name: obj
+// CHECK-NEXT:  Value: 0x1200A
+// CHECK-NEXT:  Size: 10
+// CHECK-NEXT:  Binding: Global
+// CHECK-NEXT:  Type: Object
+// CHECK-NEXT:  Other: 0
+// CHECK-NEXT:  Section: .bss
+// CHECK-NEXT: }
+
+// 0x12000 - 0 = addr(.got) = 0x12000
+// 0x1200A - 10 = addr(.got) = 0x12000
+// 0x1200A + 5 - 15 = addr(.got) = 0x12000
+// DISASM:      Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx)
+// DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx)
+// DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx)
+
+.global _start
+_start:
+  movl $1, bar at GOTOFF(%ecx)
+  movl $2, obj at GOTOFF(%ecx)
+  movl $3, obj+5 at GOTOFF(%ecx)
+  .type bar, @object
+  .comm bar, 10
+  .type obj, @object
+  .comm obj, 10




More information about the llvm-commits mailing list