diff options
author | Paul Brook <paul@codesourcery.com> | 2007-06-29 15:05:47 +0000 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2007-06-29 15:05:47 +0000 |
commit | 5ab79981933708d465b91676baf6994996979da8 (patch) | |
tree | 0a568768ea8df53fb6ba1afb1b055e99f1ca73aa /bfd/elf32-arm.c | |
parent | 32e8a950c4e551038786bc4980dcb9fbfb8384b0 (diff) | |
download | gdb-5ab79981933708d465b91676baf6994996979da8.zip gdb-5ab79981933708d465b91676baf6994996979da8.tar.gz gdb-5ab79981933708d465b91676baf6994996979da8.tar.bz2 |
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.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r-- | bfd/elf32-arm.c | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index bf4f49f..a213bab 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3236,7 +3236,8 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd, /* 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_howto_type * howto, 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_howto_type * howto, 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) |