Index: bfd/elf32-arm.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-arm.c,v retrieving revision 1.180 diff -u -p -r1.180 elf32-arm.c --- bfd/elf32-arm.c 6 Mar 2009 08:57:57 -0000 1.180 +++ bfd/elf32-arm.c 10 Mar 2009 17:12:39 -0000 @@ -3809,12 +3809,30 @@ elf32_arm_size_stubs (bfd *output_bfd, + sym_sec->output_offset + sym_sec->output_section->vma); } - else if (hash->root.root.type == bfd_link_hash_undefweak - || hash->root.root.type == bfd_link_hash_undefined) + else if (hash->root.root.type == bfd_link_hash_undefweak) /* For a shared library, these will need a PLT stub, which is treated separately. For absolute code, they cannot be handled. */ continue; + else if (hash->root.root.type == bfd_link_hash_undefined) + { + /* For a shared library, use the PLT stub as + target address to decide whether a long + branch stub is needed. */ + struct elf32_arm_link_hash_table *globals = + elf32_arm_hash_table (info); + + if (globals->splt != NULL && hash != NULL + && hash->root.plt.offset != (bfd_vma) -1) + { + sym_sec = globals->splt; + sym_value = hash->root.plt.offset; + if (sym_sec->output_section != NULL) + destination = (sym_value + + sym_sec->output_offset + + sym_sec->output_section->vma); + } + } else { bfd_set_error (bfd_error_bad_value); Index: ld/testsuite/ld-arm/arm-elf.exp =================================================================== RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v retrieving revision 1.51 diff -u -p -r1.51 arm-elf.exp --- ld/testsuite/ld-arm/arm-elf.exp 6 Mar 2009 08:57:58 -0000 1.51 +++ ld/testsuite/ld-arm/arm-elf.exp 10 Mar 2009 17:12:59 -0000 @@ -352,6 +352,12 @@ set armeabitests { {{objdump -fdw farcall-mixed-app-v5.d} {objdump -Rw farcall-mixed-app.r} {readelf -Ds farcall-mixed-app.sym}} "farcall-mixed-app-v5"} + + {"Mixed ARM/Thumb shared library with long branches" "-shared -T arm-lib.ld" "" + {farcall-mixed-lib1.s farcall-mixed-lib2.s} + {{objdump -fdw farcall-mixed-lib.d}} + "farcall-mixed-lib.so"} + } run_ld_link_tests $armeabitests Index: ld/testsuite/ld-arm/farcall-mixed-lib.d =================================================================== RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-mixed-lib.d,v retrieving revision 1.1 diff -u -p -r1.1 farcall-mixed-lib.d --- ld/testsuite/ld-arm/farcall-mixed-lib.d 5 Mar 2009 17:28:21 -0000 1.1 +++ ld/testsuite/ld-arm/farcall-mixed-lib.d 10 Mar 2009 17:13:00 -0000 @@ -22,16 +22,36 @@ Disassembly of section .text: .*: ebfffff. bl .* .*: e89d6800 ldm sp, {fp, sp, lr} .*: e12fff1e bx lr - .*: e1a00000 nop \(mov r0,r0\) - .*: e1a00000 nop \(mov r0,r0\) - .*: e1a00000 nop \(mov r0,r0\) - + ... + .*: e1a00000 .word 0xe1a00000 + .*: e1a00000 .word 0xe1a00000 + .*: e1a00000 .word 0xe1a00000 .* : + .*: f000 e806 blx 10002d0 <__app_func2_from_thumb> .*: 4770 bx lr .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) + +.* <__app_func2_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 10002d8 <__app_func2_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: feffffb0 .word 0xfeffffb0 + ... + +.* : + .*: f000 e806 blx 20002f0 <__app_func2_from_thumb> + .*: 4770 bx lr + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) + +.* <__app_func2_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 20002f8 <__app_func2_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: fdffff90 .word 0xfdffff90 + .*: 00000000 .word 0x00000000 Index: ld/testsuite/ld-arm/farcall-mixed-lib1.s =================================================================== RCS file: ld/testsuite/ld-arm/farcall-mixed-lib1.s diff -N ld/testsuite/ld-arm/farcall-mixed-lib1.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-arm/farcall-mixed-lib1.s 10 Mar 2009 17:13:00 -0000 @@ -0,0 +1,27 @@ +@ Create a large shared library so that calls through PLT to an undef +@ symbol require insertion of a long branch stub. + + .text + .arch armv5t + + .p2align 4 + .globl lib_func1 + .type lib_func1, %function +lib_func1: + mov ip, sp + stmdb sp!, {r11, ip, lr, pc} + bl app_func2 + ldmia sp, {r11, sp, lr} + bx lr + .size lib_func1, . - lib_func1 + + .space 0x1000000 + .p2align 4 + .globl lib_func2 + .type lib_func2, %function + .thumb_func + .code 16 +lib_func2: + bl app_func2 + bx lr + .size lib_func2, . - lib_func2 Index: ld/testsuite/ld-arm/farcall-mixed-lib2.s =================================================================== RCS file: ld/testsuite/ld-arm/farcall-mixed-lib2.s diff -N ld/testsuite/ld-arm/farcall-mixed-lib2.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-arm/farcall-mixed-lib2.s 10 Mar 2009 17:13:00 -0000 @@ -0,0 +1,16 @@ +@ Create a large shared library so that calls through PLT to an undef +@ symbol require insertion of a long branch stub. + + .text + .arch armv5t + + .space 0x1000000 + .p2align 4 + .globl lib_func3 + .type lib_func3, %function + .thumb_func + .code 16 +lib_func3: + bl app_func2 + bx lr + .size lib_func3, . - lib_func3