This is the mail archive of the binutils@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]

[PATCH] Improved branches to weak symbols


Hi,

the attached patch improves the instructions to generate when branching to weak symbols.

Rather than jumping to the next instruction, NOPs are generated, and selected according to the architecture.

Please let me know if OK to commit.

Thanks!
	Daniel.

-----

	bfd/
	* elf32-arm.c (arch_has_thumb2_nop): New function.
	(arch_has_arm_nop): New function.
	(elf32_arm_final_link_relocate): NOP opcodes changed.

	ld/testsuite/
	* ld-arm/callweak.d: Opcodes updated.
	* ld-arm/callweak.s: Architecture specified.
	* ld-arm/callweak-2.d: New test case.
	* ld-arm/callweak-2.s: New file.


-- Daniel Gutson CodeSourcery www.codesourcery.com
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.209
diff -u -p -r1.209 elf32-arm.c
--- bfd/elf32-arm.c	10 Aug 2009 15:56:30 -0000	1.209
+++ bfd/elf32-arm.c	13 Aug 2009 20:37:52 -0000
@@ -2987,6 +2987,26 @@ using_thumb2 (struct elf32_arm_link_hash
   return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7;
 }
 
+/* Determine what kind of NOPs are available.  */
+
+static bfd_boolean
+arch_has_arm_nop (struct elf32_arm_link_hash_table *globals)
+{
+  const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+					     Tag_CPU_arch);
+  return arch == TAG_CPU_ARCH_V6T2
+	 || arch == TAG_CPU_ARCH_V6K
+	 || arch == TAG_CPU_ARCH_V7;
+}
+
+static bfd_boolean
+arch_has_thumb2_nop (struct elf32_arm_link_hash_table *globals)
+{
+  const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+					     Tag_CPU_arch);
+  return arch == TAG_CPU_ARCH_V6T2 || arch == TAG_CPU_ARCH_V7;
+}
+
 static bfd_boolean
 arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
 {
@@ -7073,13 +7093,19 @@ elf32_arm_final_link_relocate (reloc_how
 
 	  /* A branch to an undefined weak symbol is turned into a jump to
 	     the next instruction unless a PLT entry will be created.
-	     Do the same for local undefined symbols.  */
+	     Do the same for local undefined symbols.
+	     The jump to the next instruction is optimized as a NOP depending
+	     on the architecture.  */
 	  if (h ? (h->root.type == bfd_link_hash_undefweak
 		   && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
 	      : bfd_is_und_section (sym_sec))
 	    {
-	      value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
-		      | 0x0affffff;
+	      value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000);
+
+	      if (arch_has_arm_nop (globals))
+		value |= 0x0320f000;
+	      else
+		value |= 0x01a00000; /* Using pre-UAL nop: mov r0, r0.  */
 	    }
 	  else
 	    {
@@ -7324,15 +7350,25 @@ elf32_arm_final_link_relocate (reloc_how
 	bfd_vma check;
 	bfd_signed_vma signed_check;
 	int bitsize;
-	int thumb2 = using_thumb2 (globals);
+	const int thumb2 = using_thumb2 (globals);
 
 	/* A branch to an undefined weak symbol is turned into a jump to
-	   the next instruction unless a PLT entry will be created.  */
+	   the next instruction unless a PLT entry will be created.
+	   The jump to the next instruction is optimized as a NOP.W for
+	   Thumb-2 enabled architectures.  */
 	if (h && h->root.type == bfd_link_hash_undefweak
 	    && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
 	  {
-	    bfd_put_16 (input_bfd, 0xe000, hit_data);
-	    bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+	    if (arch_has_thumb2_nop (globals))
+	      {
+		bfd_put_16 (input_bfd, 0xf3af, hit_data);
+		bfd_put_16 (input_bfd, 0x8000, hit_data + 2);
+	      }
+	    else
+	      {
+		bfd_put_16 (input_bfd, 0xe000, hit_data);
+		bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+	      }
 	    return bfd_reloc_ok;
 	  }
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.61
diff -u -p -r1.61 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	6 Aug 2009 13:05:24 -0000	1.61
+++ ld/testsuite/ld-arm/arm-elf.exp	13 Aug 2009 20:37:57 -0000
@@ -229,6 +229,9 @@ set armelftests {
     {"callweak" "-static -T arm.ld" "" {callweak.s}
      {{objdump -dr callweak.d}}
      "callweak"}
+    {"callweak-2" "-static -T arm.ld" "" {callweak-2.s}
+     {{objdump -dr callweak-2.d}}
+     "callweak-2"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/callweak-2.d
===================================================================
RCS file: ld/testsuite/ld-arm/callweak-2.d
diff -N ld/testsuite/ld-arm/callweak-2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak-2.d	13 Aug 2009 20:37:57 -0000
@@ -0,0 +1,15 @@
+
+.*:     file format.*
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000:	e320f000 	nop	\{0\}
+12340004:	0320f000 	nopeq	\{0\}
+
+12340008 <[^>]*>:
+12340008:	f3af 8000 	nop.w
+1234000c:	2000      	movs	r0, #0
+1234000e:	f3af 8000 	nop.w
+12340012:	4770      	bx	lr
+
Index: ld/testsuite/ld-arm/callweak-2.s
===================================================================
RCS file: ld/testsuite/ld-arm/callweak-2.s
diff -N ld/testsuite/ld-arm/callweak-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak-2.s	13 Aug 2009 20:37:57 -0000
@@ -0,0 +1,17 @@
+	.syntax unified
+	.arch armv6t2
+	.weak bar
+	.section .far, "ax", %progbits
+	.global	_start
+	.type	_start, %function
+_start:
+	bl bar
+	bleq bar
+	.thumb
+	.type foo, %function
+	.thumb_func
+foo:
+	bl bar
+	movs r0, #0
+	bl bar
+	bx lr
Index: ld/testsuite/ld-arm/callweak.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/callweak.d,v
retrieving revision 1.1
diff -u -p -r1.1 callweak.d
--- ld/testsuite/ld-arm/callweak.d	25 Jul 2007 14:39:48 -0000	1.1
+++ ld/testsuite/ld-arm/callweak.d	13 Aug 2009 20:37:57 -0000
@@ -4,8 +4,8 @@
 Disassembly of section .far:
 
 12340000 <[^>]*>:
-12340000:	eaffffff 	b	12340004 <[^>]*>
-12340004:	0affffff 	beq	12340008 <[^>]*>
+12340000:	e1a00000 	nop			; \(mov r0, r0\)
+12340004:	01a00000 	moveq	r0, r0
 
 12340008 <[^>]*>:
 12340008:	e000      	b.n	1234000c <[^>]*>
Index: ld/testsuite/ld-arm/callweak.s
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/callweak.s,v
retrieving revision 1.1
diff -u -p -r1.1 callweak.s
--- ld/testsuite/ld-arm/callweak.s	25 Jul 2007 14:39:48 -0000	1.1
+++ ld/testsuite/ld-arm/callweak.s	13 Aug 2009 20:37:57 -0000
@@ -1,4 +1,5 @@
 	.syntax unified
+	.arch armv6
 	.weak bar
 	.section .far, "ax", %progbits
 	.global	_start

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