Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -628,6 +628,7 @@ case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); case R_GOT_PC: + case R_GOT_PC_PLT: case R_RELAX_TLS_GD_TO_IE: return Sym.getGotVA() + A - P; case R_HEXAGON_GOT: Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -54,6 +54,9 @@ R_GOT_FROM_END, R_GOT_OFF, R_GOT_PC, + // The expression is used for IFUNC support. Used to describe the + // PC-relative address of the GOT entry containing redirection to the IPLT. + R_GOT_PC_PLT, R_HEXAGON_GOT, R_HINT, R_MIPS_GOTREL, Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -338,7 +338,8 @@ // Returns true if Expr refers a PLT entry. static bool needsPlt(RelExpr Expr) { return isRelExprOneOf(Expr); + R_GOT_PLT, R_GOT_PC_PLT, R_AARCH64_GOT_PAGE_PC_PLT>( + Expr); } // Returns true if Expr refers a GOT entry. Note that this function @@ -347,8 +348,8 @@ static bool needsGot(RelExpr Expr) { return isRelExprOneOf(Expr); + R_AARCH64_GOT_PAGE_PC_PLT, R_GOT_PC, R_GOT_PC_PLT, + 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 @@ -437,6 +438,8 @@ return R_PLT; case R_GOT: return R_GOT_PLT; + case R_GOT_PC: + return R_GOT_PC_PLT; default: return Expr; } Index: test/ELF/gotpc-relax.s =================================================================== --- test/ELF/gotpc-relax.s +++ test/ELF/gotpc-relax.s @@ -1,12 +1,8 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t1 +# RUN: llvm-objdump -D %t1 | FileCheck --check-prefix=DISASM %s # RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s -# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s - -## There is no relocations. -# RELOC: Relocations [ -# RELOC: ] # 0x201003 + 7 - 10 = 0x201000 # 0x20100a + 7 - 17 = 0x201000 @@ -24,20 +20,25 @@ # DISASM-NEXT: leaq -17(%rip), %rax # DISASM-NEXT: leaq -23(%rip), %rax # DISASM-NEXT: leaq -30(%rip), %rax -# DISASM-NEXT: movq 4058(%rip), %rax -# DISASM-NEXT: movq 4051(%rip), %rax +# IFUNC are not relaxable and accessed via the corresponding PLT entry. +# So we should generate a .got entry that points to a PLT entry that loads an entry +# from the .got.plt which is subject to an R_X86_64_IRELATIV relocation. +# 0x20101f + 8154 + 7 = 0x203000 +# DISASM-NEXT: 20101f: {{.*}} movq 8154(%rip), %rax +# DISASM-NEXT: 201026: {{.*}} movq 8147(%rip), %rax # DISASM-NEXT: leaq -52(%rip), %rax # DISASM-NEXT: leaq -59(%rip), %rax # DISASM-NEXT: leaq -65(%rip), %rax # DISASM-NEXT: leaq -72(%rip), %rax -# DISASM-NEXT: movq 4016(%rip), %rax -# DISASM-NEXT: movq 4009(%rip), %rax +# DISASM-NEXT: 201049: {{.*}} movq 8112(%rip), %rax +# DISASM-NEXT: 201050: {{.*}} movq 8105(%rip), %rax # DISASM-NEXT: callq -93 # DISASM-NEXT: callq -99 # DISASM-NEXT: callq -104 # DISASM-NEXT: callq -110 -# DISASM-NEXT: callq *3979(%rip) -# DISASM-NEXT: callq *3973(%rip) +# 0x20101f + 8154 + 6 = 0x203000 +# DISASM-NEXT: 20106f: {{.*}} callq *8075(%rip) +# DISASM-NEXT: 201075: {{.*}} callq *8069(%rip) # DISASM-NEXT: jmp -128 # DISASM-NEXT: nop # DISASM-NEXT: jmp -134 @@ -46,8 +47,33 @@ # DISASM-NEXT: nop # DISASM-NEXT: jmp -145 # DISASM-NEXT: nop -# DISASM-NEXT: jmpq *3943(%rip) -# DISASM-NEXT: jmpq *3937(%rip) +# 201093 + 8039 + 6 = 0x203000 +# DISASM-NEXT: 201093: {{.*}} jmpq *8039(%rip) +# DISASM-NEXT: 201099: {{.*}} jmpq *8033(%rip) + +# DISASM: Disassembly of section .plt: +# DISASM-NEXT: .plt: +# 0x2010a0 + 3930 + 6 = 0x202000 = address of .got.plt entry. +# DISASM-NEXT: 2010a0: {{.*}} jmpq *3930(%rip) + +# We have a R_X86_64_IRELATIVE relocation for this entry. +# DISASM: Disassembly of section .got.plt: +# DISASM-NEXT: .got.plt: +# DISASM-NEXT: 202000: + +## GOT[0] contains 0x2010a0. It is an address of PLT entry for ifunc. +# DISASM: Disassembly of section .got: +# DISASM-NEXT: .got: +# DISASM-NEXT: 203000: a0 +# DISASM-NEXT: 203001: 10 20 +# DISASM-NEXT: 203003: 00 + +## We have one relocation in IPLT for `ifunc` +# RELOC: Relocations [ +# RELOC-NEXT: Section {{.*}} .rela.plt { +# RELOC-NEXT: 0x202000 R_X86_64_IRELATIVE - 0x201002 +# RELOC-NEXT: } +# RELOC-NEXT: ] .text .globl foo