@@ -5739,6 +5739,23 @@ aarch64_relocation_aginst_gp_p (bfd_reloc_code_real_type reloc)
|| reloc == BFD_RELOC_AARCH64_MOVW_GOTOFF_G1);
}
+/* Transform an ADRP instruction to a move instruction. */
+
+#define AARCH64_MOVZ_ZERO_OPCODE 0xd2800000U
+
+static void
+rewrite_adrp_as_mov_zero (bfd_byte *location)
+{
+ uint32_t insn = bfd_getl32 (location);
+ unsigned int rd = insn & 0x1f;
+
+ bfd_putl32 (AARCH64_MOVZ_ZERO_OPCODE | rd, location);
+}
+
+static void
+clear_erratum_843419_entry (struct elf_aarch64_link_hash_table *,
+ bfd_vma, asection *);
+
/* Perform a relocation as part of a final link. The input relocation type
should be TLS relaxed. */
@@ -6554,8 +6571,25 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
if (save_addend)
return bfd_reloc_continue;
- return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type,
- howto, value, optimize_relocations);
+ bfd_reloc_status_type status
+ = _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type,
+ howto, value,
+ optimize_relocations);
+
+ if (status == bfd_reloc_ok
+ && optimize_relocations
+ && h != NULL
+ && h->root.type == bfd_link_hash_undefweak
+ && bfd_r_type == BFD_RELOC_AARCH64_ADR_HI21_PCREL
+ && value == 0)
+ {
+ rewrite_adrp_as_mov_zero (hit_data);
+ /* We have relaxed the adrp into a mov, we may have to clear any
+ pending erratum fixes. */
+ clear_erratum_843419_entry (globals, rel->r_offset, input_section);
+ }
+
+ return status;
}
/* LP64 and ILP32 operates on x- and w-registers respectively.
@@ -6625,7 +6659,7 @@ _bfd_aarch64_erratum_843419_clear_stub (struct bfd_hash_entry *gen_entry,
return false;
}
-/* TLS Relaxations may relax an adrp sequence that matches the erratum 843419
+/* Relaxations may replace an adrp sequence that matches the erratum 843419
sequence. In this case the erratum no longer applies and we need to remove
the entry from the pending stub generation. This clears matching adrp insn
at ADRP_OFFSET in INPUT_SECTION in the stub table defined in GLOBALS. */
@@ -6634,7 +6668,7 @@ static void
clear_erratum_843419_entry (struct elf_aarch64_link_hash_table *globals,
bfd_vma adrp_offset, asection *input_section)
{
- if (globals->fix_erratum_843419 & ERRAT_ADRP)
+ if (globals->fix_erratum_843419 & (ERRAT_ADR | ERRAT_ADRP))
{
struct erratum_843419_branch_to_stub_clear_data data;
data.adrp_offset = adrp_offset;
@@ -66,10 +66,16 @@ run_dump_test "erratum843419-far-adr"
run_dump_test "erratum843419-far-full"
run_dump_test "erratum843419-full"
run_dump_test "erratum843419-no-args"
+run_dump_test_lp64 "weak-undefined-adrp-erratum-full"
+run_dump_test_lp64 "weak-undefined-adrp-erratum-adr"
run_dump_test "erratum835769-843419"
# Relocation Tests
run_dump_test_lp64 "weak-undefined"
+run_dump_test_lp64 "weak-undefined-adrp"
+run_dump_test_lp64 "weak-undefined-adrp-norelax"
+run_dump_test "weak-undefined-adrp-ilp32"
+run_dump_test "weak-undefined-adrp-norelax-ilp32"
run_dump_test "emit-relocs-22"
run_dump_test "emit-relocs-23"
run_dump_test "emit-relocs-28"
new file mode 100644
@@ -0,0 +1,15 @@
+#source: weak-undefined-adrp-erratum.s
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=adr
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: d2800000 mov x0, #0x0.*
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0.*
+ 401008: f9402001 ldr x1, \[x0, #64\]
+ 40100c: d503201f nop
+#...
new file mode 100644
@@ -0,0 +1,15 @@
+#source: weak-undefined-adrp-erratum.s
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=full
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: d2800000 mov x0, #0x0.*
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0.*
+ 401008: f9402001 ldr x1, \[x0, #64\]
+ 40100c: d503201f nop
+#...
new file mode 100644
@@ -0,0 +1,10 @@
+ .balign 0x1000
+ .weak weak_sym
+ .globl _start
+_start:
+ .skip 0xffc
+ adrp x0, weak_sym
+ str x2, [x2]
+ mov x2, #0
+ ldr x1, [x0, #0x40]
+ nop
new file mode 100644
@@ -0,0 +1,17 @@
+#source: weak-undefined-adrp.s
+#as: -mabi=ilp32
+#ld: -m [aarch64_choose_ilp32_emul] -Ttext 0xF0000000 -e _start
+#objdump: -d
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: d2800000 mov x0, #0x0.*
+ *[0-9a-f]+: d2800007 mov x7, #0x0.*
+ *[0-9a-f]+: b0000004 adrp x4, .*
+ *[0-9a-f]+: 90000003 adrp x3, .*
+
+[0-9a-f]+ <defined_sym>:
+ *[0-9a-f]+: d503201f nop
new file mode 100644
@@ -0,0 +1,17 @@
+#source: weak-undefined-adrp.s
+#as: -mabi=ilp32
+#ld: -m [aarch64_choose_ilp32_emul] -Ttext 0xF0000000 -e _start --no-relax
+#objdump: -d
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: 90000000 adrp x0, .*
+ *[0-9a-f]+: 90000007 adrp x7, .*
+ *[0-9a-f]+: b0000004 adrp x4, .*
+ *[0-9a-f]+: 90000003 adrp x3, .*
+
+[0-9a-f]+ <defined_sym>:
+ *[0-9a-f]+: d503201f nop
new file mode 100644
@@ -0,0 +1,16 @@
+#source: weak-undefined-adrp.s
+#ld: -Ttext 0xF0000000 -e _start --no-relax
+#objdump: -d
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: 90000000 adrp x0, .*
+ *[0-9a-f]+: 90000007 adrp x7, .*
+ *[0-9a-f]+: b0000004 adrp x4, .*
+ *[0-9a-f]+: 90000003 adrp x3, .*
+
+[0-9a-f]+ <defined_sym>:
+ *[0-9a-f]+: d503201f nop
new file mode 100644
@@ -0,0 +1,16 @@
+#source: weak-undefined-adrp.s
+#ld: -Ttext 0xF0000000 -e _start
+#objdump: -d
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: d2800000 mov x0, #0x0.*
+ *[0-9a-f]+: d2800007 mov x7, #0x0.*
+ *[0-9a-f]+: b0000004 adrp x4, .*
+ *[0-9a-f]+: 90000003 adrp x3, .*
+
+[0-9a-f]+ <defined_sym>:
+ *[0-9a-f]+: d503201f nop
new file mode 100644
@@ -0,0 +1,10 @@
+ .text
+ .weak weak_sym
+ .global _start
+_start:
+ adrp x0, weak_sym
+ adrp x7, weak_sym
+ adrp x4, weak_sym + 0x1000
+ adrp x3, defined_sym
+defined_sym:
+ nop
@@ -14,5 +14,5 @@
+f0000024: d503201f nop
+f0000028: 58000000 ldr x0, f0000028 <main\+0x28>
+f000002c: 10000000 adr x0, f000002c <main\+0x2c>
- +f0000030: 90000000 adrp x0, f0000000 <main>
+ +f0000030: d2800000 mov x0, #0x0.*
+f0000034: d503201f nop