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