This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
ARM calls to udefined functions
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Fri, 29 Jun 2007 16:05:36 +0100
- Subject: 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