From ae0319b54454f575369b608250aaaea32935f3eb Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 16 Jan 2019 13:24:02 +0000 Subject: [ELF][AArch64] Add R_AARCH64_PLT_PAGE_PC to isRelExpr As a follow on to D56666 (r351186) there is a case when taking the address of an ifunc when linking -pie that can generate a spurious can't create dynamic relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol in readonly segment. Specifically the case is where the ifunc is in the same translation unit as the address taker, so given -fpie the compiler knows the ifunc is defined in the executable so it can use a non-got-generating relocation. The error message is due to R_AARCH64_PLT_PAGE_PC not being added to isRelExpr, its non PLT equivalent R_AARCH64_PAGE_PC is already in isRelExpr. Differential Revision: https://reviews.llvm.org/D56724 --- lld/ELF/Relocations.cpp | 2 +- lld/test/ELF/aarch64-gnu-ifunc-address-pie.s | 44 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/aarch64-gnu-ifunc-address-pie.s diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 812468896f0..9ffe8a9cc72 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -356,7 +356,7 @@ static bool needsGot(RelExpr Expr) { static bool isRelExpr(RelExpr Expr) { return isRelExprOneOf(Expr); + R_AARCH64_PLT_PAGE_PC, R_RELAX_GOT_PC>(Expr); } // Returns true if a given relocation can be computed at link-time. diff --git a/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s b/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s new file mode 100644 index 00000000000..3db9070dbd0 --- /dev/null +++ b/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s @@ -0,0 +1,44 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o +# RUN: ld.lld -pie %t.o -o %tout +# RUN: llvm-objdump -D %tout | FileCheck %s +# RUN: llvm-readobj -r %tout | FileCheck %s -check-prefix=CHECK-RELOCS + +# Test that when we take the address of a preemptible ifunc using -fpie, we can +# handle the case when the ifunc is in the same translation unit as the address +# taker. In this case the compiler knows that ifunc is not defined in a shared +# library so it can use a non got generating relative reference. +.text +.globl myfunc +.type myfunc,@gnu_indirect_function +myfunc: + ret + +.text +.globl main +.type main,@function +main: + adrp x8, myfunc + add x8, x8, :lo12: myfunc + ret + +# CHECK: 0000000000010000 myfunc: +# CHECK-NEXT: 10000: c0 03 5f d6 ret +# CHECK: 0000000000010004 main: +# CHECK-NEXT: 10004: 08 00 00 90 adrp x8, #0 +# x8 = 0x10000 +# CHECK-NEXT: 10008: 08 41 00 91 add x8, x8, #16 +# x8 = 0x10010 = .plt for myfunc +# CHECK-NEXT: 1000c: c0 03 5f d6 ret +# CHECK-NEXT: Disassembly of section .plt: +# CHECK-NEXT: 0000000000010010 .plt: +# CHECK-NEXT: 10010: 90 00 00 90 adrp x16, #65536 +# CHECK-NEXT: 10014: 11 02 40 f9 ldr x17, [x16] +# CHECK-NEXT: 10018: 10 02 00 91 add x16, x16, #0 +# CHECK-NEXT: 1001c: 20 02 1f d6 br x17 + +# CHECK-RELOCS: Relocations [ +# CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt { +# CHECK-RELOCS-NEXT: 0x20000 R_AARCH64_IRELATIVE - 0x10000 +# CHECK-RELOCS-NEXT: } +# CHECK-RELOCS-NEXT: ] -- cgit v1.2.3