[lld] r347650 - [ELF] - Fix R_AARCH64_ADR_GOT_PAGE, R_AARCH64_LD64_GOT_LO12 handling against IFUNC symbols.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 27 02:30:46 PST 2018


Author: grimar
Date: Tue Nov 27 02:30:46 2018
New Revision: 347650

URL: http://llvm.org/viewvc/llvm-project?rev=347650&view=rev
Log:
[ELF] - Fix R_AARCH64_ADR_GOT_PAGE, R_AARCH64_LD64_GOT_LO12 handling against IFUNC symbols.

This is https://bugs.llvm.org/show_bug.cgi?id=38074.

The issue is that when calling a function, LLD generates a
.got entry that points to the IFUNC resolver function when
instead, it should use the PLT entries properly for
handling the IFUNC.

So we should create a got entry that points to PLT entry,
which itself loads the value from 
.got.plt, relocated with R_*_IRELATIVE to make things work.
Patch do that.

Differential revision: https://reviews.llvm.org/D54314

Added:
    lld/trunk/test/ELF/aarch64-gnu-ifunc2.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=347650&r1=347649&r2=347650&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Nov 27 02:30:46 2018
@@ -605,6 +605,7 @@ static uint64_t getRelocTargetVA(const I
   case R_ARM_SBREL:
     return Sym.getVA(A) - getARMStaticBase(Sym);
   case R_GOT:
+  case R_GOT_PLT:
   case R_RELAX_TLS_GD_TO_IE_ABS:
     return Sym.getGotVA() + A;
   case R_GOTONLY_PC:
@@ -623,6 +624,7 @@ static uint64_t getRelocTargetVA(const I
   case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
     return Sym.getGotOffset() + A;
   case R_AARCH64_GOT_PAGE_PC:
+  case R_AARCH64_GOT_PAGE_PC_PLT:
   case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
     return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P);
   case R_GOT_PC:

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=347650&r1=347649&r2=347650&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Tue Nov 27 02:30:46 2018
@@ -324,8 +324,8 @@ static bool isAbsoluteValue(const Symbol
 
 // Returns true if Expr refers a PLT entry.
 static bool needsPlt(RelExpr Expr) {
-  return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_AARCH64_PLT_PAGE_PC>(
-      Expr);
+  return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_AARCH64_PLT_PAGE_PC,
+                        R_GOT_PLT, R_AARCH64_GOT_PAGE_PC_PLT>(Expr);
 }
 
 // Returns true if Expr refers a GOT entry. Note that this function
@@ -334,7 +334,8 @@ static bool needsPlt(RelExpr Expr) {
 static bool needsGot(RelExpr Expr) {
   return isRelExprOneOf<R_GOT, R_GOT_OFF, R_HEXAGON_GOT, R_MIPS_GOT_LOCAL_PAGE,
                         R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC,
-                        R_GOT_PC, R_GOT_FROM_END>(Expr);
+                        R_AARCH64_GOT_PAGE_PC_PLT, R_GOT_PC, R_GOT_FROM_END,
+                        R_GOT_PLT>(Expr);
 }
 
 // True if this expression is of the form Sym - X, where X is a position in the
@@ -417,8 +418,12 @@ static RelExpr toPlt(RelExpr Expr) {
     return R_PLT_PC;
   case R_AARCH64_PAGE_PC:
     return R_AARCH64_PLT_PAGE_PC;
+  case R_AARCH64_GOT_PAGE_PC:
+    return R_AARCH64_GOT_PAGE_PC_PLT;
   case R_ABS:
     return R_PLT;
+  case R_GOT:
+    return R_GOT_PLT;
   default:
     return Expr;
   }
@@ -746,7 +751,14 @@ static void addPltEntry(PltSection *Plt,
 template <class ELFT> static void addGotEntry(Symbol &Sym) {
   In.Got->addEntry(Sym);
 
-  RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS;
+  RelExpr Expr;
+  if (Sym.isTls())
+    Expr = R_TLS;
+  else if (Sym.isGnuIFunc())
+    Expr = R_PLT;
+  else
+    Expr = R_ABS;
+
   uint64_t Off = Sym.getGotOffset();
 
   // If a GOT slot value can be calculated at link-time, which is now,

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=347650&r1=347649&r2=347650&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Tue Nov 27 02:30:46 2018
@@ -34,12 +34,19 @@ enum RelExpr {
   R_ABS,
   R_ADDEND,
   R_AARCH64_GOT_PAGE_PC,
+  // The expression is used for IFUNC support. Describes PC-relative
+  // address of the memory page of GOT entry. This entry is used for
+  // a redirection to IPLT.
+  R_AARCH64_GOT_PAGE_PC_PLT,
   R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
   R_AARCH64_PAGE_PC,
   R_AARCH64_PLT_PAGE_PC,
   R_AARCH64_TLSDESC_PAGE,
   R_ARM_SBREL,
   R_GOT,
+  // The expression is used for IFUNC support. Evaluates to GOT entry,
+  // containing redirection to the IPLT.
+  R_GOT_PLT,
   R_GOTONLY_PC,
   R_GOTONLY_PC_FROM_END,
   R_GOTREL,

Added: lld/trunk/test/ELF/aarch64-gnu-ifunc2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-gnu-ifunc2.s?rev=347650&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-gnu-ifunc2.s (added)
+++ lld/trunk/test/ELF/aarch64-gnu-ifunc2.s Tue Nov 27 02:30:46 2018
@@ -0,0 +1,52 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+# RUN: ld.lld -static %t.o -o %tout
+# RUN: llvm-objdump -D %tout | FileCheck %s
+# RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC
+
+# CHECK:      Disassembly of section .text:
+# CHECK-NEXT: myfunc:
+# CHECK-NEXT:   210000:
+
+# CHECK:      main:
+# adrp x8, 0x230000, 0x230000 == address in .got
+# CHECK-NEXT:   210004: {{.*}} adrp    x8, #131072
+# CHECK-NEXT:   210008: {{.*}} ldr     x8, [x8]
+# CHECK-NEXT:   21000c: {{.*}} ret
+
+# CHECK:      Disassembly of section .plt:
+# CHECK-NEXT: .plt:
+# adrp x16, 0x220000, 0x220000 == address in .got.plt
+# CHECK-NEXT:   210010: {{.*}} adrp    x16, #65536
+# CHECK-NEXT:   210014: {{.*}} ldr     x17, [x16]
+# CHECK-NEXT:   210018: {{.*}} add     x16, x16, #0
+# CHECK-NEXT:   21001c: {{.*}} br      x17
+
+# CHECK:      Disassembly of section .got.plt:
+# CHECK-NEXT: .got.plt:
+# CHECK-NEXT:   220000:
+
+# CHECK:      Disassembly of section .got:
+# CHECK-NEXT: .got:
+# 0x210010 == address in .plt
+# CHECK-NEXT:   230000: 10 00 21 00
+
+# RELOC:      Relocations [
+# RELOC-NEXT:   Section {{.*}} .rela.plt {
+# RELOC-NEXT:     0x220000 R_AARCH64_IRELATIVE - 0x210000
+# RELOC-NEXT:   }
+# RELOC-NEXT: ]
+
+.text
+.globl myfunc
+.type myfunc, at gnu_indirect_function
+myfunc:
+ ret
+
+.text
+.globl main
+.type main, at function
+main:
+ adrp x8, :got:myfunc
+ ldr  x8, [x8, :got_lo12:myfunc]
+ ret




More information about the llvm-commits mailing list