aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorWill Newton <willnewton@sourceware.org>2013-06-07 18:57:03 +0000
committerWill Newton <willnewton@sourceware.org>2013-06-07 18:57:03 +0000
commit692e2b8bcdd8325ebfbe1daace87100d53d15ad6 (patch)
tree4dde4f3bf5a4d4f5bcba51daf8e1f1fb19fc34fa /ld
parent4ec7020176a1aaae1adeeb1e1695975ebdc172ea (diff)
downloadgdb-692e2b8bcdd8325ebfbe1daace87100d53d15ad6.zip
gdb-692e2b8bcdd8325ebfbe1daace87100d53d15ad6.tar.gz
gdb-692e2b8bcdd8325ebfbe1daace87100d53d15ad6.tar.bz2
aarch64: Add support for GNU indirect functions.
Add support for STT_GNU_IFUNC symbols to the AArch64 bfd backend. The tests are ported from the ld-ifunc tests but are enabled for cross builds so can be run easily without hardware or a simulator. bfd/ChangeLog: 2013-06-07 Will Newton <will.newton@linaro.org> * configure: Regenerate. * configure.in: Build elf-ifunc.o for AArch64. * elf64-aarch64.c: Include objalloc.h. (elf64_aarch64_howto_dynrelocs): Add R_AARCH64_IRELATIVE howto. (struct elf64_aarch64_link_hash_table): Add members for handling R_AARCH64_IRELATIVE relocations. (elf_aarch64_local_htab_hash): New function. (elf_aarch64_local_htab_eq): New function. (elf_aarch64_get_local_sym_hash): New function. (elf64_aarch64_link_hash_table_create): Initialize local STT_GNU_IFUNC symbol hash. (elf64_aarch64_hash_table_free): Free local STT_GNU_IFUNC symbol hash. (elf64_aarch64_final_link_relocate): Add sym argument. Add support for handling STT_GNU_IFUNC symbols. (elf64_aarch64_gc_sweep_hook): Add support for garbage collecting references to STT_GNU_IFUNC symbols. (elf64_aarch64_adjust_dynamic_symbol): Add support for handling STT_GNU_IFUNC symbols. (elf64_aarch64_check_relocs): Add support for handling STT_GNU_IFUNC symbols. Ensure we don't increase plt.refcount from -1 to 0. (elf64_aarch64_post_process_headers): Call _bfd_elf_set_osabi. (elf64_aarch64_is_function_type): Remove function. (elf64_aarch64_allocate_dynrelocs): Call _bfd_elf_allocate_ifunc_dyn_relocs for STT_GNU_IFUNC symbols. (elf_aarch64_allocate_local_dynrelocs): New function. (elf64_aarch64_size_dynamic_sections): Call elf_aarch64_allocate_local_dynrelocs. Initialize next_irelative_index. (elf64_aarch64_create_small_pltn_entry): Add info argument. Add support for creating .iplt entries for STT_GNU_IFUNC symbols. (elf64_aarch64_finish_dynamic_symbol): Add support for handling STT_GNU_IFUNC symbols and .iplt. (elf_aarch64_finish_local_dynamic_symbol): New function. (elf64_aarch64_finish_dynamic_sections): Call elf_aarch64_finish_local_dynamic_symbol. (elf64_aarch64_add_symbol_hook): New function. include/elf/ChangeLog: 2013-06-07 Will Newton <will.newton@linaro.org> * aarch64.h: Add R_AARCH64_IRELATIVE reloc. ld/ChangeLog: 2013-06-07 Will Newton <will.newton@linaro.org> * emulparams/aarch64elf.sh: Add IREL_IN_PLT. ld/testsuite/ChangeLog: 2013-06-07 Will Newton <will.newton@linaro.org> * ld-ifunc/ifunc.exp: Enable ifunc tests for AArch64. * ld-aarch64/aarch64-elf.exp: Add ifunc tests. * ld-aarch64/ifunc-1-local.d: New file. * ld-aarch64/ifunc-1-local.s: Likewise. * ld-aarch64/ifunc-1.d: Likewise. * ld-aarch64/ifunc-1.s: Likewise. * ld-aarch64/ifunc-10.d: Likewise. * ld-aarch64/ifunc-10.s: Likewise. * ld-aarch64/ifunc-11.d: Likewise. * ld-aarch64/ifunc-11.s: Likewise. * ld-aarch64/ifunc-12.d: Likewise. * ld-aarch64/ifunc-12.s: Likewise. * ld-aarch64/ifunc-13.d: Likewise. * ld-aarch64/ifunc-13a.s: Likewise. * ld-aarch64/ifunc-13b.s: Likewise. * ld-aarch64/ifunc-14a.d: Likewise. * ld-aarch64/ifunc-14a.s: Likewise. * ld-aarch64/ifunc-14b.d: Likewise. * ld-aarch64/ifunc-14b.s: Likewise. * ld-aarch64/ifunc-14c.d: Likewise. * ld-aarch64/ifunc-14c.s: Likewise. * ld-aarch64/ifunc-14d.d: Likewise. * ld-aarch64/ifunc-14e.d: Likewise. * ld-aarch64/ifunc-14f.d: Likewise. * ld-aarch64/ifunc-15.d: Likewise. * ld-aarch64/ifunc-15.s: Likewise. * ld-aarch64/ifunc-16.d: Likewise. * ld-aarch64/ifunc-16.s: Likewise. * ld-aarch64/ifunc-17a.d: Likewise. * ld-aarch64/ifunc-17a.s: Likewise. * ld-aarch64/ifunc-17b.d: Likewise. * ld-aarch64/ifunc-17b.s: Likewise. * ld-aarch64/ifunc-18a.d: Likewise. * ld-aarch64/ifunc-18a.s: Likewise. * ld-aarch64/ifunc-18b.d: Likewise. * ld-aarch64/ifunc-18b.s: Likewise. * ld-aarch64/ifunc-19a.d: Likewise. * ld-aarch64/ifunc-19a.s: Likewise. * ld-aarch64/ifunc-19b.d: Likewise. * ld-aarch64/ifunc-19b.s: Likewise. * ld-aarch64/ifunc-2-local.d: Likewise. * ld-aarch64/ifunc-2-local.s: Likewise. * ld-aarch64/ifunc-2.d: Likewise. * ld-aarch64/ifunc-2.s: Likewise. * ld-aarch64/ifunc-20.d: Likewise. * ld-aarch64/ifunc-20.s: Likewise. * ld-aarch64/ifunc-3.s: Likewise. * ld-aarch64/ifunc-3a.d: Likewise. * ld-aarch64/ifunc-3b.d: Likewise. * ld-aarch64/ifunc-4.d: Likewise. * ld-aarch64/ifunc-4.s: Likewise. * ld-aarch64/ifunc-4a.d: Likewise. * ld-aarch64/ifunc-5-local.s: Likewise. * ld-aarch64/ifunc-5.s: Likewise. * ld-aarch64/ifunc-5a-local.d: Likewise. * ld-aarch64/ifunc-5a.d: Likewise. * ld-aarch64/ifunc-5b-local.d: Likewise. * ld-aarch64/ifunc-5b.d: Likewise. * ld-aarch64/ifunc-5r-local.d: Likewise. * ld-aarch64/ifunc-6.s: Likewise. * ld-aarch64/ifunc-6a.d: Likewise. * ld-aarch64/ifunc-6b.d: Likewise. * ld-aarch64/ifunc-7.s: Likewise. * ld-aarch64/ifunc-7a.d: Likewise. * ld-aarch64/ifunc-7b.d: Likewise. * ld-aarch64/ifunc-8.d: Likewise. * ld-aarch64/ifunc-8a.s: Likewise. * ld-aarch64/ifunc-8b.s: Likewise. * ld-aarch64/ifunc-9.d: Likewise. * ld-aarch64/ifunc-9.s: Likewise.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog4
-rw-r--r--ld/testsuite/ChangeLog73
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp40
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-1-local.d7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-1-local.s13
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-1.d7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-1.s16
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-10.d5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-10.s25
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-11.d5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-11.s26
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-12.d5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-12.s24
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-13.d13
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-13a.s11
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-13b.s5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14a.d10
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14a.s7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14b.d10
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14b.s5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14c.d10
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14c.s7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14d.d10
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14e.d11
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-14f.d11
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-15.d12
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-15.s11
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-16.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-16.s17
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-17a.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-17a.s11
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-17b.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-17b.s6
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-18a.d14
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-18a.s5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-18b.d14
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-18b.s15
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-19a.d13
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-19a.s5
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-19b.d13
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-19b.s15
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-2-local.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-2-local.s18
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-2.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-2.s18
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-20.d12
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-20.s16
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-3.s16
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-3a.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-3b.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-4.d7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-4.s18
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-4a.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5-local.s19
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5.s20
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5a-local.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5a.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5b-local.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5b.d12
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-5r-local.d10
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-6.s21
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-6a.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-6b.d12
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-7.s21
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-7a.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-7b.d8
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-8.d9
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-8a.s13
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-8b.s7
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-9.d3
-rw-r--r--ld/testsuite/ld-aarch64/ifunc-9.s23
-rw-r--r--ld/testsuite/ld-ifunc/ifunc.exp3
72 files changed, 905 insertions, 1 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index bf40303..adfd304 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-07 Will Newton <will.newton@linaro.org>
+
+ * emulparams/aarch64elf.sh: Add IREL_IN_PLT.
+
2013-06-07 Nick Clifton <nickc@redhat.com>
* ld.texinfo (SEGMENT_START): Rephrase to indicate that a -T
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 8d959db..c2c9806 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,76 @@
+2013-06-07 Will Newton <will.newton@linaro.org>
+
+ * ld-ifunc/ifunc.exp: Enable ifunc tests for AArch64.
+ * ld-aarch64/aarch64-elf.exp: Add ifunc tests.
+ * ld-aarch64/ifunc-1-local.d: New file.
+ * ld-aarch64/ifunc-1-local.s: Likewise.
+ * ld-aarch64/ifunc-1.d: Likewise.
+ * ld-aarch64/ifunc-1.s: Likewise.
+ * ld-aarch64/ifunc-10.d: Likewise.
+ * ld-aarch64/ifunc-10.s: Likewise.
+ * ld-aarch64/ifunc-11.d: Likewise.
+ * ld-aarch64/ifunc-11.s: Likewise.
+ * ld-aarch64/ifunc-12.d: Likewise.
+ * ld-aarch64/ifunc-12.s: Likewise.
+ * ld-aarch64/ifunc-13.d: Likewise.
+ * ld-aarch64/ifunc-13a.s: Likewise.
+ * ld-aarch64/ifunc-13b.s: Likewise.
+ * ld-aarch64/ifunc-14a.d: Likewise.
+ * ld-aarch64/ifunc-14a.s: Likewise.
+ * ld-aarch64/ifunc-14b.d: Likewise.
+ * ld-aarch64/ifunc-14b.s: Likewise.
+ * ld-aarch64/ifunc-14c.d: Likewise.
+ * ld-aarch64/ifunc-14c.s: Likewise.
+ * ld-aarch64/ifunc-14d.d: Likewise.
+ * ld-aarch64/ifunc-14e.d: Likewise.
+ * ld-aarch64/ifunc-14f.d: Likewise.
+ * ld-aarch64/ifunc-15.d: Likewise.
+ * ld-aarch64/ifunc-15.s: Likewise.
+ * ld-aarch64/ifunc-16.d: Likewise.
+ * ld-aarch64/ifunc-16.s: Likewise.
+ * ld-aarch64/ifunc-17a.d: Likewise.
+ * ld-aarch64/ifunc-17a.s: Likewise.
+ * ld-aarch64/ifunc-17b.d: Likewise.
+ * ld-aarch64/ifunc-17b.s: Likewise.
+ * ld-aarch64/ifunc-18a.d: Likewise.
+ * ld-aarch64/ifunc-18a.s: Likewise.
+ * ld-aarch64/ifunc-18b.d: Likewise.
+ * ld-aarch64/ifunc-18b.s: Likewise.
+ * ld-aarch64/ifunc-19a.d: Likewise.
+ * ld-aarch64/ifunc-19a.s: Likewise.
+ * ld-aarch64/ifunc-19b.d: Likewise.
+ * ld-aarch64/ifunc-19b.s: Likewise.
+ * ld-aarch64/ifunc-2-local.d: Likewise.
+ * ld-aarch64/ifunc-2-local.s: Likewise.
+ * ld-aarch64/ifunc-2.d: Likewise.
+ * ld-aarch64/ifunc-2.s: Likewise.
+ * ld-aarch64/ifunc-20.d: Likewise.
+ * ld-aarch64/ifunc-20.s: Likewise.
+ * ld-aarch64/ifunc-3.s: Likewise.
+ * ld-aarch64/ifunc-3a.d: Likewise.
+ * ld-aarch64/ifunc-3b.d: Likewise.
+ * ld-aarch64/ifunc-4.d: Likewise.
+ * ld-aarch64/ifunc-4.s: Likewise.
+ * ld-aarch64/ifunc-4a.d: Likewise.
+ * ld-aarch64/ifunc-5-local.s: Likewise.
+ * ld-aarch64/ifunc-5.s: Likewise.
+ * ld-aarch64/ifunc-5a-local.d: Likewise.
+ * ld-aarch64/ifunc-5a.d: Likewise.
+ * ld-aarch64/ifunc-5b-local.d: Likewise.
+ * ld-aarch64/ifunc-5b.d: Likewise.
+ * ld-aarch64/ifunc-5r-local.d: Likewise.
+ * ld-aarch64/ifunc-6.s: Likewise.
+ * ld-aarch64/ifunc-6a.d: Likewise.
+ * ld-aarch64/ifunc-6b.d: Likewise.
+ * ld-aarch64/ifunc-7.s: Likewise.
+ * ld-aarch64/ifunc-7a.d: Likewise.
+ * ld-aarch64/ifunc-7b.d: Likewise.
+ * ld-aarch64/ifunc-8.d: Likewise.
+ * ld-aarch64/ifunc-8a.s: Likewise.
+ * ld-aarch64/ifunc-8b.s: Likewise.
+ * ld-aarch64/ifunc-9.d: Likewise.
+ * ld-aarch64/ifunc-9.s: Likewise.
+
2013-06-04 Roland McGrath <mcgrathr@google.com>
* ld-size/size.exp: For *-*-nacl* targets, use options_regsub(ld)
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index d687cc2..58236e2 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -114,3 +114,43 @@ run_dump_test "gc-tls-relocs"
run_dump_test "gc-plt-relocs"
run_dump_test "gc-relocs-257-dyn"
run_dump_test "gc-relocs-257"
+
+# ifunc tests
+run_dump_test "ifunc-1"
+run_dump_test "ifunc-1-local"
+run_dump_test "ifunc-2"
+run_dump_test "ifunc-2-local"
+run_dump_test "ifunc-3a"
+run_dump_test "ifunc-3b"
+run_dump_test "ifunc-4"
+run_dump_test "ifunc-4a"
+run_dump_test "ifunc-5a"
+run_dump_test "ifunc-5b"
+run_dump_test "ifunc-5a-local"
+run_dump_test "ifunc-5b-local"
+run_dump_test "ifunc-5r-local"
+run_dump_test "ifunc-6a"
+run_dump_test "ifunc-6b"
+run_dump_test "ifunc-7a"
+run_dump_test "ifunc-7b"
+run_dump_test "ifunc-8"
+run_dump_test "ifunc-9"
+run_dump_test "ifunc-10"
+run_dump_test "ifunc-11"
+run_dump_test "ifunc-12"
+run_dump_test "ifunc-13"
+run_dump_test "ifunc-14a"
+run_dump_test "ifunc-14b"
+run_dump_test "ifunc-14c"
+run_dump_test "ifunc-14d"
+run_dump_test "ifunc-14e"
+run_dump_test "ifunc-14f"
+run_dump_test "ifunc-15"
+run_dump_test "ifunc-16"
+run_dump_test "ifunc-17a"
+run_dump_test "ifunc-17b"
+run_dump_test "ifunc-18a"
+run_dump_test "ifunc-18b"
+run_dump_test "ifunc-19a"
+run_dump_test "ifunc-19b"
+run_dump_test "ifunc-20"
diff --git a/ld/testsuite/ld-aarch64/ifunc-1-local.d b/ld/testsuite/ld-aarch64/ifunc-1-local.d
new file mode 100644
index 0000000..0cce7f6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-1-local.d
@@ -0,0 +1,7 @@
+#ld: -shared
+#objdump: -dw
+#target: aarch64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2a0@plt>
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-1-local.s b/ld/testsuite/ld-aarch64/ifunc-1-local.s
new file mode 100644
index 0000000..7b9d117
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-1-local.s
@@ -0,0 +1,13 @@
+ .type foo, %gnu_indirect_function
+ .set __GI_foo, foo
+ .text
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ bl __GI_foo
+ ret
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-1.d b/ld/testsuite/ld-aarch64/ifunc-1.d
new file mode 100644
index 0000000..8a17cd7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-1.d
@@ -0,0 +1,7 @@
+#ld: -shared
+#objdump: -dw
+#target: aarch64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-1.s b/ld/testsuite/ld-aarch64/ifunc-1.s
new file mode 100644
index 0000000..6f86c8a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-1.s
@@ -0,0 +1,16 @@
+ .type foo, %gnu_indirect_function
+ .global __GI_foo
+ .hidden __GI_foo
+ .set __GI_foo, foo
+ .text
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ bl __GI_foo
+ ret
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-10.d b/ld/testsuite/ld-aarch64/ifunc-10.d
new file mode 100644
index 0000000..6931c7f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-10.d
@@ -0,0 +1,5 @@
+#ld: -e bar --gc-sections
+#readelf: -r --wide
+#target: aarch64-*-*
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-aarch64/ifunc-10.s b/ld/testsuite/ld-aarch64/ifunc-10.s
new file mode 100644
index 0000000..10468c1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-10.s
@@ -0,0 +1,25 @@
+ .section .text.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .global foo
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ bl ifunc
+ adrp x0, xxx
+ add x0, x0, :lo12:xxx
+ ret
+
+ .section .text.bar,"ax",@progbits
+ .type bar, @function
+bar:
+ .global bar
+ ret
+
+ .section .text.ifunc,"ax",@progbits
+ .type ifunc, @gnu_indirect_function
+ifunc:
+ ret
+
+ .section .data.foo,"aw",@progbits
+xxx:
+ .quad ifunc
diff --git a/ld/testsuite/ld-aarch64/ifunc-11.d b/ld/testsuite/ld-aarch64/ifunc-11.d
new file mode 100644
index 0000000..6931c7f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-11.d
@@ -0,0 +1,5 @@
+#ld: -e bar --gc-sections
+#readelf: -r --wide
+#target: aarch64-*-*
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-aarch64/ifunc-11.s b/ld/testsuite/ld-aarch64/ifunc-11.s
new file mode 100644
index 0000000..e1820de
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-11.s
@@ -0,0 +1,26 @@
+ .section .text.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .global foo
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ bl ifunc
+ adrp x0, xxx
+ add x0, x0, :lo12:xxx
+ ret
+
+ .section .text.bar,"ax",@progbits
+ .type bar, @function
+bar:
+ .global bar
+ ret
+
+ .section .text.ifunc,"ax",@progbits
+ .type ifunc, @gnu_indirect_function
+ .global ifunc
+ifunc:
+ ret
+
+ .section .data.foo,"aw",@progbits
+xxx:
+ .quad ifunc
diff --git a/ld/testsuite/ld-aarch64/ifunc-12.d b/ld/testsuite/ld-aarch64/ifunc-12.d
new file mode 100644
index 0000000..55fe925
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-12.d
@@ -0,0 +1,5 @@
+#ld: -shared -e bar --gc-sections
+#readelf: -r --wide
+#target: aarch64-*-*
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-aarch64/ifunc-12.s b/ld/testsuite/ld-aarch64/ifunc-12.s
new file mode 100644
index 0000000..aad30df
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-12.s
@@ -0,0 +1,24 @@
+ .section .text.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ bl ifunc
+ adrp x0, xxx
+ add x0, x0, :lo12:xxx
+ ret
+
+ .section .text.bar,"ax",@progbits
+ .type bar, @function
+bar:
+ .global bar
+ ret
+
+ .section .text.ifunc,"ax",@progbits
+ .type ifunc, @gnu_indirect_function
+ifunc:
+ ret
+
+ .section .data.foo,"aw",@progbits
+xxx:
+ .quad ifunc
diff --git a/ld/testsuite/ld-aarch64/ifunc-13.d b/ld/testsuite/ld-aarch64/ifunc-13.d
new file mode 100644
index 0000000..191d839
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-13.d
@@ -0,0 +1,13 @@
+#source: ifunc-13a.s
+#source: ifunc-13b.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ABS64[ ]+ifunc\(\)[ ]+ifunc \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0
diff --git a/ld/testsuite/ld-aarch64/ifunc-13a.s b/ld/testsuite/ld-aarch64/ifunc-13a.s
new file mode 100644
index 0000000..873e06e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-13a.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo, @function
+ .global foo
+foo:
+ adrp x0, xxx
+ add x0, x0, :lo12:xxx
+ ret
+
+ .data
+xxx:
+ .quad ifunc
diff --git a/ld/testsuite/ld-aarch64/ifunc-13b.s b/ld/testsuite/ld-aarch64/ifunc-13b.s
new file mode 100644
index 0000000..3560394
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-13b.s
@@ -0,0 +1,5 @@
+ .text
+ .type ifunc, @gnu_indirect_function
+ .globl ifunc
+ifunc:
+ ret
diff --git a/ld/testsuite/ld-aarch64/ifunc-14a.d b/ld/testsuite/ld-aarch64/ifunc-14a.d
new file mode 100644
index 0000000..174d20f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14a.d
@@ -0,0 +1,10 @@
+#source: ifunc-14a.s
+#source: ifunc-14b.s
+#ld: -shared -z nocombreloc
+#readelf: -d
+#target: aarch64-*-*
+
+#failif
+#...
+.*\(TEXTREL\).*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-14a.s b/ld/testsuite/ld-aarch64/ifunc-14a.s
new file mode 100644
index 0000000..7d6183c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14a.s
@@ -0,0 +1,7 @@
+ .text
+ .globl bar
+ .type bar, @function
+bar:
+ bl foo
+ .size bar, .-bar
+ .hidden foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-14b.d b/ld/testsuite/ld-aarch64/ifunc-14b.d
new file mode 100644
index 0000000..509a3a2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14b.d
@@ -0,0 +1,10 @@
+#source: ifunc-14b.s
+#source: ifunc-14a.s
+#ld: -shared -z nocombreloc
+#readelf: -d
+#target: aarch64-*-*
+
+#failif
+#...
+.*\(TEXTREL\).*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-14b.s b/ld/testsuite/ld-aarch64/ifunc-14b.s
new file mode 100644
index 0000000..bac22eb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14b.s
@@ -0,0 +1,5 @@
+ .type foo, %gnu_indirect_function
+ .globl foo
+foo:
+ ret
+ .size foo, .-foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-14c.d b/ld/testsuite/ld-aarch64/ifunc-14c.d
new file mode 100644
index 0000000..0b63753
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14c.d
@@ -0,0 +1,10 @@
+#source: ifunc-14a.s
+#source: ifunc-14b.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#failif
+#...
+.* +R_AARCH64_NONE +.*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-14c.s b/ld/testsuite/ld-aarch64/ifunc-14c.s
new file mode 100644
index 0000000..7853280
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14c.s
@@ -0,0 +1,7 @@
+ .text
+ .globl xxx
+ .type xxx, @function
+xxx:
+ bl foo
+ .size xxx, .-xxx
+ .hidden foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-14d.d b/ld/testsuite/ld-aarch64/ifunc-14d.d
new file mode 100644
index 0000000..fd08f03
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14d.d
@@ -0,0 +1,10 @@
+#source: ifunc-14b.s
+#source: ifunc-14a.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#failif
+#...
+.* +R_AARCH64_NONE +.*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-14e.d b/ld/testsuite/ld-aarch64/ifunc-14e.d
new file mode 100644
index 0000000..37c470b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14e.d
@@ -0,0 +1,11 @@
+#source: ifunc-14a.s
+#source: ifunc-14c.s
+#source: ifunc-14b.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#failif
+#...
+.* +R_AARCH64_NONE +.*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-14f.d b/ld/testsuite/ld-aarch64/ifunc-14f.d
new file mode 100644
index 0000000..3fad96f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-14f.d
@@ -0,0 +1,11 @@
+#source: ifunc-14a.s
+#source: ifunc-14b.s
+#source: ifunc-14c.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#failif
+#...
+.* +R_AARCH64_NONE +.*
+#...
diff --git a/ld/testsuite/ld-aarch64/ifunc-15.d b/ld/testsuite/ld-aarch64/ifunc-15.d
new file mode 100644
index 0000000..79a9a77
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-15.d
@@ -0,0 +1,12 @@
+#source: ifunc-15.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.got' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+ifunc\(\)[ ]+ifunc \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0
diff --git a/ld/testsuite/ld-aarch64/ifunc-15.s b/ld/testsuite/ld-aarch64/ifunc-15.s
new file mode 100644
index 0000000..f94b4a6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-15.s
@@ -0,0 +1,11 @@
+ .text
+ .type foo, @function
+ .global foo
+foo:
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ ret
+ .type ifunc, @gnu_indirect_function
+ .globl ifunc
+ifunc:
+ ret
diff --git a/ld/testsuite/ld-aarch64/ifunc-16.d b/ld/testsuite/ld-aarch64/ifunc-16.d
new file mode 100644
index 0000000..1336257
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-16.d
@@ -0,0 +1,9 @@
+#source: ifunc-16.s
+#ld: -shared
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+0+[ ]+ifunc \+ 0
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-16.s b/ld/testsuite/ld-aarch64/ifunc-16.s
new file mode 100644
index 0000000..ded401a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-16.s
@@ -0,0 +1,17 @@
+ .text
+ .globl fct
+ .type fct, @gnu_indirect_function
+ .set fct,resolve
+ .hidden int_fct
+ .globl int_fct
+ .set int_fct,fct
+ .p2align 4,,15
+ .type resolve, @function
+resolve:
+ bl ifunc
+ .size resolve, .-resolve
+ .globl g
+ .type g, @function
+g:
+ bl int_fct
+ .size g, .-g
diff --git a/ld/testsuite/ld-aarch64/ifunc-17a.d b/ld/testsuite/ld-aarch64/ifunc-17a.d
new file mode 100644
index 0000000..b414be3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-17a.d
@@ -0,0 +1,9 @@
+#source: ifunc-17a.s
+#source: ifunc-17b.s
+#ld: -static
+#readelf: -s --wide
+#target: aarch64-*-*
+
+#...
+ +[0-9]+: +[0-9a-f]+ +4 +OBJECT +GLOBAL +DEFAULT +[1-9] foo
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-17a.s b/ld/testsuite/ld-aarch64/ifunc-17a.s
new file mode 100644
index 0000000..e0bde49
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-17a.s
@@ -0,0 +1,11 @@
+ .globl main
+ .globl start
+ .globl _start
+ .globl __start
+ .text
+main:
+start:
+_start:
+__start:
+ .byte 0
+ .common foo,4,4
diff --git a/ld/testsuite/ld-aarch64/ifunc-17b.d b/ld/testsuite/ld-aarch64/ifunc-17b.d
new file mode 100644
index 0000000..1566bcb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-17b.d
@@ -0,0 +1,9 @@
+#source: ifunc-17b.s
+#source: ifunc-17a.s
+#ld: -static
+#readelf: -s --wide
+#target: aarch64-*-*
+
+#...
+ +[0-9]+: +[0-9a-f]+ +4 +OBJECT +GLOBAL +DEFAULT +[1-9] foo
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-17b.s b/ld/testsuite/ld-aarch64/ifunc-17b.s
new file mode 100644
index 0000000..66abe04
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-17b.s
@@ -0,0 +1,6 @@
+ .weak foo
+ .type foo, %gnu_indirect_function
+ .size foo,1
+ .text
+foo:
+ .byte 1
diff --git a/ld/testsuite/ld-aarch64/ifunc-18a.d b/ld/testsuite/ld-aarch64/ifunc-18a.d
new file mode 100644
index 0000000..682e7a3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-18a.d
@@ -0,0 +1,14 @@
+#source: ifunc-18a.s
+#source: ifunc-18b.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-18a.s b/ld/testsuite/ld-aarch64/ifunc-18a.s
new file mode 100644
index 0000000..c29c121
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-18a.s
@@ -0,0 +1,5 @@
+ .section .data.rel,"aw",@progbits
+ .globl foo_ptrt
+ .type foo_ptr, @object
+foo_ptr:
+ .dc.a foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-18b.d b/ld/testsuite/ld-aarch64/ifunc-18b.d
new file mode 100644
index 0000000..40b39e1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-18b.d
@@ -0,0 +1,14 @@
+#source: ifunc-18b.s
+#source: ifunc-18a.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-18b.s b/ld/testsuite/ld-aarch64/ifunc-18b.s
new file mode 100644
index 0000000..2e46c1e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-18b.s
@@ -0,0 +1,15 @@
+ .text
+ .type foo, %gnu_indirect_function
+ .hidden foo
+ .globl foo
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+bar:
+ bl foo1
+ ret
+ .size bar, .-bar
+ .hidden foo1
+ .globl foo1
+ foo1 = foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-19a.d b/ld/testsuite/ld-aarch64/ifunc-19a.d
new file mode 100644
index 0000000..9f083c9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-19a.d
@@ -0,0 +1,13 @@
+#source: ifunc-19a.s
+#source: ifunc-19b.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-19a.s b/ld/testsuite/ld-aarch64/ifunc-19a.s
new file mode 100644
index 0000000..3a3d0cd
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-19a.s
@@ -0,0 +1,5 @@
+ .section .data.rel,"aw",@progbits
+ .globl foo_ptrt
+ .type foo_ptr, @object
+foo_ptr:
+ .dc.a foo1
diff --git a/ld/testsuite/ld-aarch64/ifunc-19b.d b/ld/testsuite/ld-aarch64/ifunc-19b.d
new file mode 100644
index 0000000..dea5b16
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-19b.d
@@ -0,0 +1,13 @@
+#source: ifunc-19b.s
+#source: ifunc-19a.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-19b.s b/ld/testsuite/ld-aarch64/ifunc-19b.s
new file mode 100644
index 0000000..2e46c1e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-19b.s
@@ -0,0 +1,15 @@
+ .text
+ .type foo, %gnu_indirect_function
+ .hidden foo
+ .globl foo
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+bar:
+ bl foo1
+ ret
+ .size bar, .-bar
+ .hidden foo1
+ .globl foo1
+ foo1 = foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-2-local.d b/ld/testsuite/ld-aarch64/ifunc-2-local.d
new file mode 100644
index 0000000..07616ca
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-2-local.d
@@ -0,0 +1,9 @@
+#ld: -shared
+#objdump: -dw
+#target: aarch64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
+[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+x0, 0 <_GLOBAL_OFFSET_TABLE_>
+[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+x0, x0, #0x2b0
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-2-local.s b/ld/testsuite/ld-aarch64/ifunc-2-local.s
new file mode 100644
index 0000000..da350df
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-2-local.s
@@ -0,0 +1,18 @@
+ .type foo, %gnu_indirect_function
+ .global __GI_foo
+ .hidden __GI_foo
+ .set __GI_foo, foo
+ .text
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ bl __GI_foo
+ adrp x0, __GI_foo
+ add x0, x0, :lo12:__GI_foo
+ ret
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-2.d b/ld/testsuite/ld-aarch64/ifunc-2.d
new file mode 100644
index 0000000..07616ca
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-2.d
@@ -0,0 +1,9 @@
+#ld: -shared
+#objdump: -dw
+#target: aarch64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
+[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+x0, 0 <_GLOBAL_OFFSET_TABLE_>
+[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+x0, x0, #0x2b0
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-2.s b/ld/testsuite/ld-aarch64/ifunc-2.s
new file mode 100644
index 0000000..da350df
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-2.s
@@ -0,0 +1,18 @@
+ .type foo, %gnu_indirect_function
+ .global __GI_foo
+ .hidden __GI_foo
+ .set __GI_foo, foo
+ .text
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ bl __GI_foo
+ adrp x0, __GI_foo
+ add x0, x0, :lo12:__GI_foo
+ ret
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-20.d b/ld/testsuite/ld-aarch64/ifunc-20.d
new file mode 100644
index 0000000..cee34bf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-20.d
@@ -0,0 +1,12 @@
+#source: ifunc-20.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ABS64[ ]+ifunc\(\)[ ]+ifunc \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0
diff --git a/ld/testsuite/ld-aarch64/ifunc-20.s b/ld/testsuite/ld-aarch64/ifunc-20.s
new file mode 100644
index 0000000..17393cb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-20.s
@@ -0,0 +1,16 @@
+ .section .data.rel,"aw",@progbits
+ .globl ifunc_ptrt
+ .type ifunc_ptr, @object
+ifunc_ptr:
+ .dc.a ifunc
+ .text
+ .type ifunc, @gnu_indirect_function
+ .globl ifunc
+ifunc:
+ ret
+ .size ifunc, .-ifunc
+ .type bar, @function
+ .globl bar
+bar:
+ bl ifunc
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-3.s b/ld/testsuite/ld-aarch64/ifunc-3.s
new file mode 100644
index 0000000..c68b1b7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-3.s
@@ -0,0 +1,16 @@
+ .type foo, %gnu_indirect_function
+ .global __GI_foo
+ .protected __GI_foo
+ .set __GI_foo, foo
+ .text
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ bl __GI_foo
+ ret
+ .size bar, .-bar
diff --git a/ld/testsuite/ld-aarch64/ifunc-3a.d b/ld/testsuite/ld-aarch64/ifunc-3a.d
new file mode 100644
index 0000000..1335480
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-3a.d
@@ -0,0 +1,8 @@
+#source: ifunc-3.s
+#ld: -shared
+#objdump: -dw
+#target: aarch64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2e0@plt>
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-3b.d b/ld/testsuite/ld-aarch64/ifunc-3b.d
new file mode 100644
index 0000000..d90ed5c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-3b.d
@@ -0,0 +1,8 @@
+#source: ifunc-3.s
+#ld: -shared
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#...
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-4.d b/ld/testsuite/ld-aarch64/ifunc-4.d
new file mode 100644
index 0000000..9a3e308
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-4.d
@@ -0,0 +1,7 @@
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+#...
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-4.s b/ld/testsuite/ld-aarch64/ifunc-4.s
new file mode 100644
index 0000000..c2b66f5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-4.s
@@ -0,0 +1,18 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ bl foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-4a.d b/ld/testsuite/ld-aarch64/ifunc-4a.d
new file mode 100644
index 0000000..3329782
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-4a.d
@@ -0,0 +1,8 @@
+#ld: -s
+#readelf: -r --wide
+#target: aarch64-*-*
+#source: ifunc-4.s
+
+#...
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
+#pass
diff --git a/ld/testsuite/ld-aarch64/ifunc-5-local.s b/ld/testsuite/ld-aarch64/ifunc-5-local.s
new file mode 100644
index 0000000..8d23bab
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5-local.s
@@ -0,0 +1,19 @@
+ .text
+ .type foo, %gnu_indirect_function
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ bl foo
+ adrp x0, :got:foo
+ ldr x0, [x0, #:got_lo12:foo]
diff --git a/ld/testsuite/ld-aarch64/ifunc-5.s b/ld/testsuite/ld-aarch64/ifunc-5.s
new file mode 100644
index 0000000..b1bbf1a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5.s
@@ -0,0 +1,20 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ bl foo
+ adrp x0, :got:foo
+ ldr x0, [x0, #:got_lo12:foo]
diff --git a/ld/testsuite/ld-aarch64/ifunc-5a-local.d b/ld/testsuite/ld-aarch64/ifunc-5a-local.d
new file mode 100644
index 0000000..8bc6862
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5a-local.d
@@ -0,0 +1,8 @@
+#source: ifunc-5-local.s
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-5a.d b/ld/testsuite/ld-aarch64/ifunc-5a.d
new file mode 100644
index 0000000..781db3c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5a.d
@@ -0,0 +1,8 @@
+#source: ifunc-5.s
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-5b-local.d b/ld/testsuite/ld-aarch64/ifunc-5b-local.d
new file mode 100644
index 0000000..b0d6dda
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5b-local.d
@@ -0,0 +1,8 @@
+#source: ifunc-5-local.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-5b.d b/ld/testsuite/ld-aarch64/ifunc-5b.d
new file mode 100644
index 0000000..82c5479
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5b.d
@@ -0,0 +1,12 @@
+#source: ifunc-5.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.got' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+foo\(\)[ ]+foo \+ 0
+#...
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0
diff --git a/ld/testsuite/ld-aarch64/ifunc-5r-local.d b/ld/testsuite/ld-aarch64/ifunc-5r-local.d
new file mode 100644
index 0000000..1c87ec1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-5r-local.d
@@ -0,0 +1,10 @@
+#source: ifunc-5-local.s
+#ld: -r
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.text' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_CALL26[ ]+foo\(\)[ ]+foo \+ 0
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ADR_GOT_PAGE[ ]+foo\(\)[ ]+foo \+ 0
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_LD64_GOT_LO1[ ]+foo\(\)[ ]+foo \+ 0
diff --git a/ld/testsuite/ld-aarch64/ifunc-6.s b/ld/testsuite/ld-aarch64/ifunc-6.s
new file mode 100644
index 0000000..56486d6d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-6.s
@@ -0,0 +1,21 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .protected foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ bl foo
+ adrp x0, :got:foo
+ ldr x0, [x0, #:got_lo12:foo]
diff --git a/ld/testsuite/ld-aarch64/ifunc-6a.d b/ld/testsuite/ld-aarch64/ifunc-6a.d
new file mode 100644
index 0000000..06b9042
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-6a.d
@@ -0,0 +1,8 @@
+#source: ifunc-6.s
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-6b.d b/ld/testsuite/ld-aarch64/ifunc-6b.d
new file mode 100644
index 0000000..8f06cd1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-6b.d
@@ -0,0 +1,12 @@
+#source: ifunc-6.s
+#ld: -shared -z nocombreloc
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.got' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+foo\(\)[ ]+foo \+ 0
+#...
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-7.s b/ld/testsuite/ld-aarch64/ifunc-7.s
new file mode 100644
index 0000000..51485af
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-7.s
@@ -0,0 +1,21 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .hidden foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ bl foo
+ adrp x0, :got:foo
+ ldr x0, [x0, #:got_lo12:foo]
diff --git a/ld/testsuite/ld-aarch64/ifunc-7a.d b/ld/testsuite/ld-aarch64/ifunc-7a.d
new file mode 100644
index 0000000..e462f90
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-7a.d
@@ -0,0 +1,8 @@
+#source: ifunc-7.s
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-7b.d b/ld/testsuite/ld-aarch64/ifunc-7b.d
new file mode 100644
index 0000000..3f6060c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-7b.d
@@ -0,0 +1,8 @@
+#source: ifunc-7.s
+#ld: -shared
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-8.d b/ld/testsuite/ld-aarch64/ifunc-8.d
new file mode 100644
index 0000000..97201bf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-8.d
@@ -0,0 +1,9 @@
+#source: ifunc-8a.s
+#source: ifunc-8b.s
+#ld:
+#readelf: -r --wide
+#target: aarch64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
diff --git a/ld/testsuite/ld-aarch64/ifunc-8a.s b/ld/testsuite/ld-aarch64/ifunc-8a.s
new file mode 100644
index 0000000..94c073a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-8a.s
@@ -0,0 +1,13 @@
+ .text
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ adrp x0, :got:foo
+ ldr x0, [x0, #:got_lo12:foo]
diff --git a/ld/testsuite/ld-aarch64/ifunc-8b.s b/ld/testsuite/ld-aarch64/ifunc-8b.s
new file mode 100644
index 0000000..1f108f8
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-8b.s
@@ -0,0 +1,7 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
diff --git a/ld/testsuite/ld-aarch64/ifunc-9.d b/ld/testsuite/ld-aarch64/ifunc-9.d
new file mode 100644
index 0000000..85f5e61
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-9.d
@@ -0,0 +1,3 @@
+#ld: --export-dynamic
+#error: .*dynamic STT_GNU_IFUNC symbol `foo' with pointer equality in `.*.o' can not be used when making an executable; recompile with -fPIE and relink with -pie
+#target: aarch64-*-*
diff --git a/ld/testsuite/ld-aarch64/ifunc-9.s b/ld/testsuite/ld-aarch64/ifunc-9.s
new file mode 100644
index 0000000..2e2f577
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-9.s
@@ -0,0 +1,23 @@
+ .text
+ .type foo, %gnu_indirect_function
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .type start,"function"
+ .global start
+start:
+ .type _start,"function"
+ .global _start
+_start:
+ .type __start,"function"
+ .global __start
+__start:
+ .type __start,"function"
+ adrp x0, .LANCHOR0
+ add x0, x0, :lo12:.LANCHOR0
+ .data
+ .align 3
+.LANCHOR0 = . + 0
+ .xword foo
diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp
index df913d8..a4cc06d 100644
--- a/ld/testsuite/ld-ifunc/ifunc.exp
+++ b/ld/testsuite/ld-ifunc/ifunc.exp
@@ -24,10 +24,11 @@
# IFUNC support has only been implemented for the ix86, x86_64, powerpc,
-# and sparc so far.
+# aarch64 and sparc so far.
if {!(([istarget "i?86-*-*"]
|| [istarget "x86_64-*-*"]
|| [istarget "powerpc*-*-*"]
+ || [istarget "aarch64-*-*"]
|| [istarget "sparc*-*-*"])
&& ([istarget "*-*-elf*"]
|| [istarget "*-*-nacl*"]