From 79202c378f2d33e1cca457a93d7bfa22b78556a9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 31 Aug 2016 23:24:11 +0000 Subject: [PATCH] Fix the implementation of R_386_GOTPC and R_386_GOTOFF. They were both pointing to the start of the got, not the end. Fixes pr28924. llvm-svn: 280310 --- lld/ELF/InputSection.cpp | 5 +++++ lld/ELF/Relocations.cpp | 3 ++- lld/ELF/Relocations.h | 2 ++ lld/ELF/Target.cpp | 4 ++-- lld/test/ELF/relocation-i686.s | 6 ++++-- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index f349141..aad9bc7 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -223,6 +223,9 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, return Body.getSize() + A; case R_GOTREL: return Body.getVA(A) - Out::Got->getVA(); + case R_GOTREL_FROM_END: + return Body.getVA(A) - Out::Got->getVA() - + Out::Got->getSize(); case R_RELAX_TLS_GD_TO_IE_END: case R_GOT_FROM_END: return Body.getGotOffset() + A - Out::Got->getSize(); @@ -237,6 +240,8 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, return Body.getGotVA() + A - P; case R_GOTONLY_PC: return Out::Got->getVA() + A - P; + case R_GOTONLY_PC_FROM_END: + return Out::Got->getVA() + A - P + Out::Got->getSize(); case R_RELAX_TLS_LD_TO_LE: case R_RELAX_TLS_IE_TO_LE: case R_RELAX_TLS_GD_TO_LE: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 9a29483..d10b594 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -574,7 +574,8 @@ static void scanRelocs(InputSectionBase &C, ArrayRef 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::Got->HasGotOffRel = true; uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body); diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 1710acc..556fab1 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -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, diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index e40baee..165647f 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -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: diff --git a/lld/test/ELF/relocation-i686.s b/lld/test/ELF/relocation-i686.s index 96d7606..262f697 100644 --- a/lld/test/ELF/relocation-i686.s +++ b/lld/test/ELF/relocation-i686.s @@ -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 -- 2.7.4