Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -605,6 +605,7 @@ 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 @@ case R_RELAX_TLS_GD_TO_IE_GOT_OFF: return Sym.getGotOffset() + A; case R_GOT_PAGE_PC: + case R_GOT_PAGE_PC_PLT: case R_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); case R_GOT_PC: Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -35,6 +35,9 @@ R_ADDEND, 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, @@ -42,6 +45,10 @@ R_GOT_FROM_END, R_GOT_OFF, R_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_GOT_PAGE_PC_PLT, R_GOT_PC, R_HEXAGON_GOT, R_HINT, Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -324,7 +324,8 @@ // Returns true if Expr refers a PLT entry. static bool needsPlt(RelExpr Expr) { - return isRelExprOneOf(Expr); + return isRelExprOneOf(Expr); } // Returns true if Expr refers a GOT entry. Note that this function @@ -333,7 +334,8 @@ static bool needsGot(RelExpr Expr) { return isRelExprOneOf(Expr); + R_GOT_PC, R_GOT_FROM_END, R_GOT_PLT, R_GOT_PAGE_PC_PLT>( + Expr); } // True if this expression is of the form Sym - X, where X is a position in the @@ -417,6 +419,10 @@ return R_PLT_PAGE_PC; case R_ABS: return R_PLT; + case R_GOT: + return R_GOT_PLT; + case R_GOT_PAGE_PC: + return R_GOT_PAGE_PC_PLT; default: return Expr; } @@ -743,7 +749,14 @@ template 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, Index: test/ELF/aarch64-gnu-ifunc2.s =================================================================== --- test/ELF/aarch64-gnu-ifunc2.s +++ test/ELF/aarch64-gnu-ifunc2.s @@ -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,@gnu_indirect_function +myfunc: + ret + +.text +.globl main +.type main,@function +main: + adrp x8, :got:myfunc + ldr x8, [x8, :got_lo12:myfunc] + ret