This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [AArch64] Relax long branch veneer insertion for non STT_FUNC symbol


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2f340668a9a7c00f8813b097b157b07fba8cfa82

commit 2f340668a9a7c00f8813b097b157b07fba8cfa82
Author: Jiong Wang <jiong.wang@arm.com>
Date:   Wed Jan 20 16:57:59 2016 +0000

    [AArch64] Relax long branch veneer insertion for non STT_FUNC symbol
    
      As defined at AArch64 ELF Specification (4.6.7 Call and Jump
      relocations), symbol with type of non STT_FUNC but in different input
      section with relocation place should insert long branch veneer also.
    
      Meanwhile the current long branch veneer infrastructure havn't considered
      the situation where the branch destination is "sym_value + rela->addend".
    
      This was OK because we only insert veneer for long call destination is
      STT_FUNC symbol for which the addend is always zero. But as we relax the
      support to other situations by this patch, we need to handle addend be
      non-zero value. For example, for static function, relocation against
      "local symbol" are turned into relocation against "section symbol + offset"
      where there is a valid addend.
    
      bfd/
    	* elfnn-aarch64.c (aarch64_type_of_stub): Allow insert long branch
    	veneer for sym_sec != input_sec.
    	(elfNN_aarch64_size_stub): Support STT_SECTION symbol.
    	(elfNN_aarch64_final_link_relocate): Take rela addend into account when
    	calculation destination.
    
      ld/
    	* testsuite/ld-aarch64/farcall-section.d: Delete.
    	* testsuite/ld-aarch64/farcall-section.s: Delete.
    	* testsuite/ld-aarch64/farcall-b-section.d: New expectation file.
    	* testsuite/ld-aarch64/farcall-bl-section.d: Likewise.
    	* testsuite/ld-aarch64/farcall-b-section.s: New testcase.
    	* testsuite/ld-aarch64/farcall-bl-section.s: Likewise.
    	* testsuite/ld-aarch64/aarch64-elf.exp: Likewise.

Diff:
---
 bfd/ChangeLog                                      |  8 +++++
 bfd/elfnn-aarch64.c                                | 25 ++++++++++++----
 ld/ChangeLog                                       | 10 +++++++
 ld/testsuite/ld-aarch64/aarch64-elf.exp            |  3 +-
 ld/testsuite/ld-aarch64/farcall-b-none-function.d  | 21 ++++++++++++-
 ld/testsuite/ld-aarch64/farcall-b-section.d        | 34 ++++++++++++++++++++++
 ld/testsuite/ld-aarch64/farcall-b-section.s        | 20 +++++++++++++
 ld/testsuite/ld-aarch64/farcall-bl-none-function.d | 21 ++++++++++++-
 ld/testsuite/ld-aarch64/farcall-bl-section.d       | 34 ++++++++++++++++++++++
 ld/testsuite/ld-aarch64/farcall-bl-section.s       | 20 +++++++++++++
 ld/testsuite/ld-aarch64/farcall-section.d          |  5 ----
 ld/testsuite/ld-aarch64/farcall-section.s          | 19 ------------
 12 files changed, 187 insertions(+), 33 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index dcf21ce..c4fd0bb 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-21  Jiong Wang  <jiong.wang@arm.com>
+
+	* elfnn-aarch64.c (aarch64_type_of_stub): Allow insert long branch
+	veneer for sym_sec != input_sec.
+	(elfNN_aarch64_size_stub): Support STT_SECTION symbol.
+	(elfNN_aarch64_final_link_relocate): Take rela addend into account when
+	calculation destination.
+
 2016-01-21  Alan Modra  <amodra@gmail.com>
 
 	* elf-linux-core.h (swap_linux_prpsinfo32_out): New function.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 70251f1..292470df 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -2655,7 +2655,7 @@ aarch64_type_of_stub (struct bfd_link_info *info,
   bfd_boolean via_plt_p;
 
   if (st_type != STT_FUNC
-      && (sym_sec != bfd_abs_section_ptr))
+      && (sym_sec == input_sec))
     return stub_type;
 
   globals = elf_aarch64_hash_table (info);
@@ -4174,7 +4174,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 		      goto error_ret_free_internal;
 		    }
 
-		  stub_entry->target_value = sym_value;
+		  stub_entry->target_value = sym_value + irela->r_addend;
 		  stub_entry->target_section = sym_sec;
 		  stub_entry->stub_type = stub_type;
 		  stub_entry->h = hash;
@@ -5280,15 +5280,28 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 	/* Check if a stub has to be inserted because the destination
 	   is too far away.  */
 	struct elf_aarch64_stub_hash_entry *stub_entry = NULL;
-	if (! aarch64_valid_branch_p (value, place))
+
+	/* If the branch destination is directed to plt stub, "value" will be
+	   the final destination, otherwise we should plus signed_addend, it may
+	   contain non-zero value, for example call to local function symbol
+	   which are turned into "sec_sym + sec_off", and sec_off is kept in
+	   signed_addend.  */
+	if (! aarch64_valid_branch_p (via_plt_p ? value : value + signed_addend,
+				      place))
 	  /* The target is out of reach, so redirect the branch to
 	     the local stub for this function.  */
 	stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h,
 						   rel, globals);
 	if (stub_entry != NULL)
-	  value = (stub_entry->stub_offset
-		   + stub_entry->stub_sec->output_offset
-		   + stub_entry->stub_sec->output_section->vma);
+	  {
+	    value = (stub_entry->stub_offset
+		     + stub_entry->stub_sec->output_offset
+		     + stub_entry->stub_sec->output_section->vma);
+
+	    /* We have redirected the destination to stub entry address,
+	       so ignore any addend record in the original rela entry.  */
+	    signed_addend = 0;
+	  }
       }
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
 						   signed_addend, weak_undef_p);
diff --git a/ld/ChangeLog b/ld/ChangeLog
index fc01ed6..a6494b8 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+2016-01-20  Jiong Wang  <jiong.wang@arm.com>
+
+	* testsuite/ld-aarch64/farcall-section.d: Delete.
+	* testsuite/ld-aarch64/farcall-section.s: Delete.
+	* testsuite/ld-aarch64/farcall-b-section.d: New expectation file.
+	* testsuite/ld-aarch64/farcall-bl-section.d: Likewise.
+	* testsuite/ld-aarch64/farcall-b-section.s: New testcase.
+	* testsuite/ld-aarch64/farcall-bl-section.s: Likewise.
+	* testsuite/ld-aarch64/aarch64-elf.exp: Likewise.
+
 2016-01-20  Nick Clifton  <nickc@redhat.com>
 
 	PR 19457
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index c5c9ad0..939539e 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -170,7 +170,6 @@ run_dump_test "pcrel_pic_defined_local"
 
 run_dump_test "limit-b"
 run_dump_test "limit-bl"
-run_dump_test "farcall-section"
 run_dump_test "farcall-back"
 run_dump_test "farcall-b-defsym"
 run_dump_test "farcall-bl-defsym"
@@ -181,6 +180,8 @@ run_dump_test "farcall-bl"
 run_dump_test "farcall-b"
 run_dump_test "farcall-b-none-function"
 run_dump_test "farcall-bl-none-function"
+run_dump_test "farcall-b-section"
+run_dump_test "farcall-bl-section"
 
 run_dump_test "tls-relax-all"
 run_dump_test "tls-relax-gd-le"
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.d b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
index 34a6568..ba2981f 100644
--- a/ld/testsuite/ld-aarch64/farcall-b-none-function.d
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
@@ -2,4 +2,23 @@
 #source: farcall-b-none-function.s
 #as:
 #ld: -Ttext 0x1000 --section-start .foo=0x8001000
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar'.*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:	14000003 	b	100c <__bar_veneer>
+    1004:	d65f03c0 	ret
+    1008:	14000007 	b	1024 <__bar_veneer\+0x18>
+
+.* <__bar_veneer>:
+    100c:	90040010 	adrp	x16, 8001000 <bar>
+    1010:	91000210 	add	x16, x16, #0x0
+    1014:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b-section.d b/ld/testsuite/ld-aarch64/farcall-b-section.d
new file mode 100644
index 0000000..4745c0f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-section.d
@@ -0,0 +1,34 @@
+#name: aarch64-farcall-b-section
+#source: farcall-b-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:	14000008 	b	1020 <___veneer>
+    1004:	14000003 	b	1010 <___veneer>
+    1008:	d65f03c0 	ret
+    100c:	1400000d 	b	1040 <___veneer\+0x20>
+
+.* <___veneer>:
+    1010:	90040010 	adrp	x16, 8001000 <bar>
+    1014:	91001210 	add	x16, x16, #0x4
+    1018:	d61f0200 	br	x16
+    101c:	00000000 	.inst	0x00000000 ; undefined
+
+.* <___veneer>:
+    1020:	90040010 	adrp	x16, 8001000 <bar>
+    1024:	91000210 	add	x16, x16, #0x0
+    1028:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:	d65f03c0 	ret
+
+.* <bar2>:
+ 8001004:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b-section.s b/ld/testsuite/ld-aarch64/farcall-b-section.s
new file mode 100644
index 0000000..1a135ef
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-section.s
@@ -0,0 +1,20 @@
+.global _start
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	b bar2
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
+	.type bar2, @function
+bar2:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
index 6ce9ca4..b6a4dda 100644
--- a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
@@ -2,4 +2,23 @@
 #source: farcall-bl-none-function.s
 #as:
 #ld: -Ttext 0x1000 --section-start .foo=0x8001000
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against symbol `bar'.*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:	94000003 	bl	100c <__bar_veneer>
+    1004:	d65f03c0 	ret
+    1008:	14000007 	b	1024 <__bar_veneer\+0x18>
+
+.* <__bar_veneer>:
+    100c:	90040010 	adrp	x16, 8001000 <bar>
+    1010:	91000210 	add	x16, x16, #0x0
+    1014:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-section.d b/ld/testsuite/ld-aarch64/farcall-bl-section.d
new file mode 100644
index 0000000..2bd4f85
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-section.d
@@ -0,0 +1,34 @@
+#name: aarch64-farcall-bl-section
+#source: farcall-bl-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:	94000008 	bl	1020 <___veneer>
+    1004:	94000003 	bl	1010 <___veneer>
+    1008:	d65f03c0 	ret
+    100c:	1400000d 	b	1040 <___veneer\+0x20>
+
+.* <___veneer>:
+    1010:	90040010 	adrp	x16, 8001000 <bar>
+    1014:	91001210 	add	x16, x16, #0x4
+    1018:	d61f0200 	br	x16
+    101c:	00000000 	.inst	0x00000000 ; undefined
+
+.* <___veneer>:
+    1020:	90040010 	adrp	x16, 8001000 <bar>
+    1024:	91000210 	add	x16, x16, #0x0
+    1028:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:	d65f03c0 	ret
+
+.* <bar2>:
+ 8001004:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-section.s b/ld/testsuite/ld-aarch64/farcall-bl-section.s
new file mode 100644
index 0000000..4469d4d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-section.s
@@ -0,0 +1,20 @@
+	.global _start
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	bl bar2
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
+	.type bar2, @function
+bar2:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-section.d b/ld/testsuite/ld-aarch64/farcall-section.d
deleted file mode 100644
index 85775e1..0000000
--- a/ld/testsuite/ld-aarch64/farcall-section.d
+++ /dev/null
@@ -1,5 +0,0 @@
-#name: Aarch64 farcall to symbol of type STT_SECTION
-#source: farcall-section.s
-#as:
-#ld: -Ttext 0x1000 --section-start .foo=0x8001014
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against `.foo'
diff --git a/ld/testsuite/ld-aarch64/farcall-section.s b/ld/testsuite/ld-aarch64/farcall-section.s
deleted file mode 100644
index 86a070c..0000000
--- a/ld/testsuite/ld-aarch64/farcall-section.s
+++ /dev/null
@@ -1,19 +0,0 @@
-# Test to ensure that an Aarch64 call exceeding 128MB generates an error
-# if the destination is of type STT_SECTION (eg non-global symbol)
-
-	.global _start
-
-# We will place the section .text at 0x1000.
-
-	.text
-
-_start:
-	bl bar
-
-# We will place the section .foo at 0x8001020.
-
-	.section .foo, "xa"
-
-bar:
-	ret
-


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]