Fix the implementation of R_386_GOTPC and R_386_GOTOFF.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 31 Aug 2016 23:24:11 +0000 (23:24 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 31 Aug 2016 23:24:11 +0000 (23:24 +0000)
They were both pointing to the start of the got, not the end.

Fixes pr28924.

llvm-svn: 280310

lld/ELF/InputSection.cpp
lld/ELF/Relocations.cpp
lld/ELF/Relocations.h
lld/ELF/Target.cpp
lld/test/ELF/relocation-i686.s

index f349141..aad9bc7 100644 (file)
@@ -223,6 +223,9 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
     return Body.getSize<ELFT>() + A;
   case R_GOTREL:
     return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA();
+  case R_GOTREL_FROM_END:
+    return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA() -
+           Out<ELFT>::Got->getSize();
   case R_RELAX_TLS_GD_TO_IE_END:
   case R_GOT_FROM_END:
     return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->getSize();
@@ -237,6 +240,8 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
     return Body.getGotVA<ELFT>() + A - P;
   case R_GOTONLY_PC:
     return Out<ELFT>::Got->getVA() + A - P;
+  case R_GOTONLY_PC_FROM_END:
+    return Out<ELFT>::Got->getVA() + A - P + Out<ELFT>::Got->getSize();
   case R_RELAX_TLS_LD_TO_LE:
   case R_RELAX_TLS_IE_TO_LE:
   case R_RELAX_TLS_GD_TO_LE:
index 9a29483..d10b594 100644 (file)
@@ -574,7 +574,8 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
 
     // This relocation does not require got entry, but it is relative to got and
     // needs it to be created. Here we request for that.
-    if (Expr == R_GOTONLY_PC || Expr == R_GOTREL || Expr == R_PPC_TOC)
+    if (Expr == R_GOTONLY_PC || Expr == R_GOTONLY_PC_FROM_END ||
+        Expr == R_GOTREL || Expr == R_GOTREL_FROM_END || Expr == R_PPC_TOC)
       Out<ELFT>::Got->HasGotOffRel = true;
 
     uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body);
index 1710acc..556fab1 100644 (file)
@@ -22,7 +22,9 @@ enum RelExpr {
   R_ABS,
   R_GOT,
   R_GOTONLY_PC,
+  R_GOTONLY_PC_FROM_END,
   R_GOTREL,
+  R_GOTREL_FROM_END,
   R_GOT_FROM_END,
   R_GOT_OFF,
   R_GOT_PAGE_PC,
index e40baee..165647f 100644 (file)
@@ -328,7 +328,7 @@ RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
   case R_386_PC32:
     return R_PC;
   case R_386_GOTPC:
-    return R_GOTONLY_PC;
+    return R_GOTONLY_PC_FROM_END;
   case R_386_TLS_IE:
     return R_GOT;
   case R_386_GOT32:
@@ -336,7 +336,7 @@ RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
   case R_386_TLS_GOTIE:
     return R_GOT_FROM_END;
   case R_386_GOTOFF:
-    return R_GOTREL;
+    return R_GOTREL_FROM_END;
   case R_386_TLS_LE:
     return R_TLS;
   case R_386_TLS_LE_32:
index 96d7606..262f697 100644 (file)
@@ -56,16 +56,18 @@ movl bar@GOT, %eax
 // ADDR-NEXT:   SHF_WRITE
 // ADDR-NEXT: ]
 // ADDR-NEXT: Address: 0x12078
+// ADDR-NEXT: Offset:
+// ADDR-NEXT: Size: 8
 
 .section .R_386_GOTPC,"ax",@progbits
 R_386_GOTPC:
  movl $_GLOBAL_OFFSET_TABLE_, %eax
 
-// 0x12050 - 0x11014 = 4156
+// 0x12078 + 8 - 0x11014 = 4204
 
 // CHECK:      Disassembly of section .R_386_GOTPC:
 // CHECK-NEXT: R_386_GOTPC:
-// CHECK-NEXT:   11014:  {{.*}} movl  $4196, %eax
+// CHECK-NEXT:   11014:  {{.*}} movl  $4204, %eax
 
 .section .dynamic_reloc, "ax",@progbits
  call bar