aarch64: Emit jump slot for conditional branches to weak_undef

Message ID 20200515021755.87132-1-siddhesh@gotplt.org
State Superseded
Headers show
Series
  • aarch64: Emit jump slot for conditional branches to weak_undef
Related show

Commit Message

Siddhesh Poyarekar May 15, 2020, 2:17 a.m.
The linker silently writes out a conditional branch to 0 if the
target symbol in R_AARCH64_CONDBR19 or R_AARCH64_TSTBR14 relocations is
undefined.  Emit a PLT instead so that behaviour is the same for these
relocations as the llvm linker.

The special behaviour for undefined weak symbols, where conditional
branches to such symbols result in a branch unto themselves, has been
retained.  This is because the weak-undefined.s test explicitly checks
for that, leading me to conclude that it's expected behaviour.

bfd/ChangeLog:

2020-05-15  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

	* elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Club
	BFD_RELOC_AARCH64_BRANCH19 and BFD_RELOC_AARCH64_TSTBR14
	cases with BFD_RELOC_AARCH64_JUMP26.
	(elfNN_aarch64_check_relocs): Likewise.

ld/ChangeLog:

2020-05-15  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

	* testsuite/ld-aarch64/aarch64-elf.exp: New test
	emit-relocs-560.
	* testsuite/ld-aarch64/emit-relocs-560.d: New file.
	* testsuite/ld-aarch64/emit-relocs-560.s: New file.

---

 bfd/elfnn-aarch64.c                       | 22 +++++++++--
 ld/testsuite/ld-aarch64/aarch64-elf.exp   |  1 +
 ld/testsuite/ld-aarch64/emit-relocs-560.d | 47 +++++++++++++++++++++++
 ld/testsuite/ld-aarch64/emit-relocs-560.s |  3 ++
 4 files changed, 69 insertions(+), 4 deletions(-)
 create mode 100644 ld/testsuite/ld-aarch64/emit-relocs-560.d
 create mode 100644 ld/testsuite/ld-aarch64/emit-relocs-560.s

-- 
2.17.1

Comments

Florian Weimer via Binutils May 15, 2020, 10:25 a.m. | #1
Hi Siddhesh,

> 	* testsuite/ld-aarch64/aarch64-elf.exp: New test

> 	emit-relocs-560.

> 	* testsuite/ld-aarch64/emit-relocs-560.d: New file.

> 	* testsuite/ld-aarch64/emit-relocs-560.s: New file.


This new test fails when used with an aarch64 toolchain that is
configured for a big-endian default (eg aarch64_be-elf):

  regexp_diff match failure
  regexp "^ 1b8:	f9418a11 	ldr	x17, \[x16, #784\]$"
  line   " 1b8:	f9418211 	ldr	x17, [x16, #768]"
  ...and more...

Cheers
  Nick

Patch

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4bb5707d2f..02df893fcd 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -5494,6 +5494,7 @@  elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
   bfd_vma orig_value = value;
   bfd_boolean resolved_to_zero;
   bfd_boolean abs_symbol_p;
+  bfd_boolean via_plt_p;
 
   globals = elf_aarch64_hash_table (info);
 
@@ -5515,6 +5516,8 @@  elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 		  : bfd_is_und_section (sym_sec));
   abs_symbol_p = h != NULL && bfd_is_abs_symbol (&h->root);
 
+  via_plt_p = (globals->root.splt != NULL && h != NULL
+	       && h->plt.offset != (bfd_vma) - 1);
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
      it here if it is defined in a non-shared object.  */
@@ -5850,12 +5853,23 @@  elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 	value += signed_addend;
       break;
 
+    case BFD_RELOC_AARCH64_BRANCH19:
+    case BFD_RELOC_AARCH64_TSTBR14:
+      /* A conditional branch to an undefined weak symbol is converted to a
+	 branch to itself.  */
+      if (weak_undef_p && !via_plt_p)
+	{
+	  value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+						       place, value,
+						       signed_addend,
+						       weak_undef_p);
+	  break;
+	}
+      /* Fall through.  */
     case BFD_RELOC_AARCH64_CALL26:
     case BFD_RELOC_AARCH64_JUMP26:
       {
 	asection *splt = globals->root.splt;
-	bfd_boolean via_plt_p =
-	  splt != NULL && h != NULL && h->plt.offset != (bfd_vma) - 1;
 
 	/* A call to an undefined weak symbol is converted to a jump to
 	   the next instruction unless a PLT entry will be created.
@@ -5943,7 +5957,6 @@  elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_32:
 #endif
     case BFD_RELOC_AARCH64_ADD_LO12:
-    case BFD_RELOC_AARCH64_BRANCH19:
     case BFD_RELOC_AARCH64_LDST128_LO12:
     case BFD_RELOC_AARCH64_LDST16_LO12:
     case BFD_RELOC_AARCH64_LDST32_LO12:
@@ -5959,7 +5972,6 @@  elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_MOVW_G2_NC:
     case BFD_RELOC_AARCH64_MOVW_G2_S:
     case BFD_RELOC_AARCH64_MOVW_G3:
-    case BFD_RELOC_AARCH64_TSTBR14:
       value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
 						   place, value,
 						   signed_addend, weak_undef_p);
@@ -8022,6 +8034,8 @@  elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    break;
 	  }
 
+	case BFD_RELOC_AARCH64_BRANCH19:
+	case BFD_RELOC_AARCH64_TSTBR14:
 	case BFD_RELOC_AARCH64_CALL26:
 	case BFD_RELOC_AARCH64_JUMP26:
 	  /* If this is a local symbol then we resolve it
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 297a3e96db..4c44fa1642 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -236,6 +236,7 @@  run_dump_test_lp64 "emit-relocs-557"
 run_dump_test_lp64 "emit-relocs-558"
 run_dump_test_lp64 "emit-relocs-558-overflow"
 run_dump_test_lp64 "emit-relocs-559"
+run_dump_test_lp64 "emit-relocs-560"
 
 run_dump_test "reloc-overflow-bad"
 
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-560.d b/ld/testsuite/ld-aarch64/emit-relocs-560.d
new file mode 100644
index 0000000000..208aa3bbd9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-560.d
@@ -0,0 +1,47 @@ 
+#source: emit-relocs-560.s
+#ld: -shared
+#objdump: -DR -j .got.plt -j .text -j .plt
+
+.*:     file format .*
+
+
+Disassembly of section .plt:
+
+00000000000001b0 <.plt>:
+ 1b0:	a9bf7bf0 	stp	x16, x30, \[sp, #-16\]!
+ 1b4:	90000090 	adrp	x16, 10000 <foo\+0xfe10>
+ 1b8:	f9418a11 	ldr	x17, \[x16, #784\]
+ 1bc:	910c4210 	add	x16, x16, #0x310
+ 1c0:	d61f0220 	br	x17
+ 1c4:	d503201f 	nop
+ 1c8:	d503201f 	nop
+ 1cc:	d503201f 	nop
+
+00000000000001d0 <baz@plt>:
+ 1d0:	90000090 	adrp	x16, 10000 <foo\+0xfe10>
+ 1d4:	f9418e11 	ldr	x17, \[x16, #792\]
+ 1d8:	910c6210 	add	x16, x16, #0x318
+ 1dc:	d61f0220 	br	x17
+
+00000000000001e0 <bar@plt>:
+ 1e0:	90000090 	adrp	x16, 10000 <foo\+0xfe10>
+ 1e4:	f9419211 	ldr	x17, \[x16, #800\]
+ 1e8:	910c8210 	add	x16, x16, #0x320
+ 1ec:	d61f0220 	br	x17
+
+Disassembly of section .text:
+
+00000000000001f0 <foo>:
+ 1f0:	360fff80 	tbz	w0, #1, 1e0 <bar@plt>
+ 1f4:	b5fffee1 	cbnz	x1, 1d0 <baz@plt>
+
+Disassembly of section .got.plt:
+
+0000000000010300 <.got.plt>:
+	...
+   10318:	000001b0 	.*
+			10318: R_AARCH64_JUMP_SLOT	baz
+   1031c:	00000000 	.*
+   10320:	000001b0 	.*
+			10320: R_AARCH64_JUMP_SLOT	bar
+   10324:	00000000 	.*
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-560.s b/ld/testsuite/ld-aarch64/emit-relocs-560.s
new file mode 100644
index 0000000000..9529e8fd5e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-560.s
@@ -0,0 +1,3 @@ 
+foo:
+	tbz	x0, 1, bar
+	cbnz	x1, baz