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]

ARM calls to udefined functions


The ARM EABI specifies that R_ARM_CALL and R_ARM_THM_CALL against a weak 
undefined symbol result in a jump to the next instruction.

Other jump relocations are undefined, so we do the same for the ones that 
happen to be in the same case statement.

Tested on arm-none-eabi.
Applied to CVS head.

Paul

2007-06-29  Paul Brook  <paul@codesourcery.com>

	bfd/
	* elf32-arm.c (bfd_elf32_arm_process_before_allocation): Suppress
	call veneers for call relocations against undefined symbols.
	(elf32_arm_final_link_relocate): Turn call to undefined symbol
	into a jump to the next instruction.

	ld/testuite/
	* ld-arm/arm-elf.exp (armelftests): Add callweak.
	* ld-arm/callweak.d: New test.
	* ld-arm/callweak.s: New test.


Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.119
diff -u -p -r1.119 elf32-arm.c
--- bfd/elf32-arm.c	26 Jun 2007 13:55:04 -0000	1.119
+++ bfd/elf32-arm.c	29 Jun 2007 14:25:10 -0000
@@ -3236,7 +3236,8 @@ bfd_elf32_arm_process_before_allocation 
 	      /* This one is a call from thumb code.  We look
 	         up the target of the call.  If it is not a thumb
                  target, we insert glue.  */
-	      if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC && !globals->use_blx)
+	      if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC && !globals->use_blx
+		  && h->root.type != bfd_link_hash_undefweak)
 		record_thumb_to_arm_glue (link_info, h);
 	      break;
 
@@ -4812,40 +4813,43 @@ elf32_arm_final_link_relocate (reloc_how
 	  signed_addend = value;
 	  signed_addend >>= howto->rightshift;
 
-	  /* It is not an error for an undefined weak reference to be
-	     out of range.  Any program that branches to such a symbol
-	     is going to crash anyway, so there is no point worrying
-	     about getting the destination exactly right.  */
-	  if (! h || h->root.type != bfd_link_hash_undefweak)
+	  /* A branch to an undefined weak symbol is turned into a jump to
+	     the next instruction.  */
+	  if (h && h->root.type == bfd_link_hash_undefweak)
+	    {
+	      value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
+		      | 0x0affffff;
+	    }
+	  else
 	    {
 	      /* Perform a signed range check.  */
 	      if (   signed_addend >   ((bfd_signed_vma)  (howto->dst_mask >> 1))
 		  || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1)))
 		return bfd_reloc_overflow;
-	    }
 
-	  addend = (value & 2);
+	      addend = (value & 2);
 
-	  value = (signed_addend & howto->dst_mask)
-	    | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
+	      value = (signed_addend & howto->dst_mask)
+		| (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
 
-	  /* Set the H bit in the BLX instruction.  */
-	  if (sym_flags == STT_ARM_TFUNC)
-	    {
-	      if (addend)
-		value |= (1 << 24);
-	      else
-		value &= ~(bfd_vma)(1 << 24);
-	    }
-	  if (r_type == R_ARM_CALL)
-	    {
-	      /* Select the correct instruction (BL or BLX).  */
+	      /* Set the H bit in the BLX instruction.  */
 	      if (sym_flags == STT_ARM_TFUNC)
-		value |= (1 << 28);
-	      else
 		{
-		  value &= ~(bfd_vma)(1 << 28);
-		  value |= (1 << 24);
+		  if (addend)
+		    value |= (1 << 24);
+		  else
+		    value &= ~(bfd_vma)(1 << 24);
+		}
+	      if (r_type == R_ARM_CALL)
+		{
+		  /* Select the correct instruction (BL or BLX).  */
+		  if (sym_flags == STT_ARM_TFUNC)
+		    value |= (1 << 28);
+		  else
+		    {
+		      value &= ~(bfd_vma)(1 << 28);
+		      value |= (1 << 24);
+		    }
 		}
 	    }
 	  break;
@@ -5022,6 +5026,15 @@ elf32_arm_final_link_relocate (reloc_how
 	int bitsize;
 	int thumb2 = using_thumb2 (globals);
 
+	/* A branch to an undefined weak symbol is turned into a jump to
+	   the next instruction.  */
+	if (h && h->root.type == bfd_link_hash_undefweak)
+	  {
+	    bfd_put_16 (input_bfd, 0xe000, hit_data);
+	    bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+	    return bfd_reloc_ok;
+	  }
+
 	/* Fetch the addend.  We use the Thumb-2 encoding (backwards compatible
            with Thumb-1) involving the J1 and J2 bits.  */
 	if (globals->use_rel)
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.27
diff -u -p -r1.27 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	26 Jun 2007 13:55:04 -0000	1.27
+++ ld/testsuite/ld-arm/arm-elf.exp	29 Jun 2007 14:27:23 -0000
@@ -170,6 +170,9 @@ set armelftests {
      {"EABI attribute merging" "-r" "" {attr-merge.s attr-merge.s}
       {{readelf -A attr-merge.attr}}
       "attr-merge"}
+     {"callweak" "-static -T arm.ld" "" {callweak.s}
+      {{objdump -dr callweak.d}}
+      "callweak"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/callweak.d
===================================================================
RCS file: ld/testsuite/ld-arm/callweak.d
diff -N ld/testsuite/ld-arm/callweak.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak.d	29 Jun 2007 14:45:20 -0000
@@ -0,0 +1,17 @@
+
+.*:     file format.*
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000:	eaffffff 	b	12340004 <[^>]*>
+12340004:	0affffff 	beq	12340008 <[^>]*>
+
+12340008 <[^>]*>:
+12340008:	e000      	b.n	1234000c <[^>]*>
+1234000a:	bf00      	nop
+1234000c:	2000      	movs	r0, #0
+1234000e:	e000      	b.n	12340012 <[^>]*>
+12340010:	bf00      	nop
+12340012:	4770      	bx	lr
+
Index: ld/testsuite/ld-arm/callweak.s
===================================================================
RCS file: ld/testsuite/ld-arm/callweak.s
diff -N ld/testsuite/ld-arm/callweak.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak.s	29 Jun 2007 14:44:41 -0000
@@ -0,0 +1,16 @@
+	.syntax unified
+	.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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]