summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@linaro.org>2019-01-15 11:17:03 +0000
committerPeter Smith <peter.smith@linaro.org>2019-01-15 11:17:03 +0000
commitd77697520980bffdd7fc6036b77993341b736fc3 (patch)
tree5519c751a89ed3627875a0c576cb442e6e9100d7
parent3a47ee4a8435d5da1775ee5116e842ab4dcdbfc3 (diff)
[ELF][AArch64] Add missing PLT relocations to isStaticLinkTimeConstant
r347650 fixed pr38074 for AArch64 for static linking. It added two new RelExpr instances R_AARCH64_GOT_PAGE_PC_PLT and R_GOT_PLT. These need to be added to isStaticLinkTimeConstant so that the address of an ifunc can be taken when building a shared library. fixes pr40250 Differential Revision: https://reviews.llvm.org/D56666
-rw-r--r--lld/ELF/Relocations.cpp6
-rw-r--r--lld/test/ELF/aarch64-gnu-ifunc-address.s40
2 files changed, 43 insertions, 3 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index c10e5615013..812468896f0 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -374,8 +374,8 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF,
R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF,
R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD,
- R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
- R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT,
+ R_AARCH64_GOT_PAGE_PC, R_AARCH64_GOT_PAGE_PC_PLT, R_GOT_PC,
+ R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT,
R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT,
R_TLSDESC_CALL, R_AARCH64_TLSDESC_PAGE, R_HINT,
R_TLSLD_HINT, R_TLSIE_HINT>(E))
@@ -383,7 +383,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
// These never do, except if the entire file is position dependent or if
// only the low bits are used.
- if (E == R_GOT || E == R_PLT || E == R_TLSDESC)
+ if (E == R_GOT || E == R_GOT_PLT || E == R_PLT || E == R_TLSDESC)
return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
if (Sym.IsPreemptible)
diff --git a/lld/test/ELF/aarch64-gnu-ifunc-address.s b/lld/test/ELF/aarch64-gnu-ifunc-address.s
new file mode 100644
index 00000000000..9321fe35e53
--- /dev/null
+++ b/lld/test/ELF/aarch64-gnu-ifunc-address.s
@@ -0,0 +1,40 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+# RUN: ld.lld -shared %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 in a shared object
+# we get R_AARCH64_GLOB_DAT to the symbol as it could be defined in another
+# link unit and preempt our definition.
+.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
+# CHECK: 0000000000010004 main:
+# x8 = 0x30000
+# CHECK-NEXT: 10004: 08 01 00 90 adrp x8, #131072
+# x8 = 0x300e0 = .got entry for myfunc with R_AARCH64_GLOB_DAT
+# CHECK-NEXT: 10008: 08 71 40 f9 ldr x8, [x8, #224]
+# CHECK-NEXT: 1000c: c0 03 5f d6 ret
+
+# CHECK: Disassembly of section .got:
+# CHECK-NEXT: 00000000000300e0 .got:
+
+# CHECK-RELOCS: Relocations [
+# CHECK-RELOCS-NEXT: Section {{.*}} .rela.dyn {
+# CHECK-RELOCS-NEXT: 0x300E0 R_AARCH64_GLOB_DAT myfunc 0x0
+# CHECK-RELOCS-NEXT: }
+# CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt {
+# CHECK-RELOCS-NEXT: 0x20018 R_AARCH64_JUMP_SLOT myfunc 0x0
+# CHECK-RELOCS-NEXT: }
+# CHECK-RELOCS-NEXT: ]