From 5ab79981933708d465b91676baf6994996979da8 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 29 Jun 2007 15:05:47 +0000 Subject: [PATCH] 2007-06-29 Paul Brook 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. --- bfd/ChangeLog | 7 ++++ bfd/elf32-arm.c | 63 ++++++++++++++++++++------------- ld/testsuite/ChangeLog | 6 ++++ ld/testsuite/ld-arm/arm-elf.exp | 3 ++ 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ad71032f6fa..1f7f5c4bae2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2007-06-29 Paul Brook + + * 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. + 2007-06-29 Michael Snyder * bfd.c (bfd_demangle): Plug memory leak (Coverity). diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index bf4f49f5f6a..a213bab1f2e 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) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index f0a5de3f001..cd4281d521c 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-06-29 Paul Brook + + * ld-arm/arm-elf.exp (armelftests): Add callweak. + * ld-arm/callweak.d: New test. + * ld-arm/callweak.s: New test. + 2007-06-28 H.J. Lu PR ld/4701 diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 087225f2e10..a83c1eedf0b 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -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 -- 2.30.2