diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0739367678..894c497e97 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2009-04-17 Christophe Lyon + + * elf32-arm.c (elf32_arm_size_stubs): Handle long branches through + PLT entries to an undefined symbol when generating a shared + library. + 2009-04-17 Nick Clifton PR 9909 diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 99beb9e63c..2f49b7ee96 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3832,12 +3832,29 @@ 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) - /* 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) + || (hash->root.root.type == bfd_link_hash_undefweak)) + { + /* For a shared library, use the PLT stub as + target address to decide whether a long + branch stub is needed. + For absolute code, they cannot be handled. */ + 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 + continue; + } else { bfd_set_error (bfd_error_bad_value); diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 75b9050026..175ca0aecc 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-04-17 Christophe Lyon + + * ld-arm/arm-elf.exp: Add new test farcall-mixed-lib. + * ld-arm/farcall-mixed-lib.d: Update expected output. + * ld-arm/farcall-mixed-lib1.s: New file. + * ld-arm/farcall-mixed-lib2.s: New file. + 2009-04-16 Richard Sandiford * ld-powerpc/aix-export-2.s, ld-powerpc/aix-export-2.nd: New test. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 94002a1aea..b524cceef8 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -353,6 +353,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 diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib.d b/ld/testsuite/ld-arm/farcall-mixed-lib.d index ab498e4f9a..db2243fcab 100644 --- a/ld/testsuite/ld-arm/farcall-mixed-lib.d +++ b/ld/testsuite/ld-arm/farcall-mixed-lib.d @@ -14,24 +14,56 @@ Disassembly of section .plt: .*: e28fc6.* add ip, pc, #.* ; 0x.* .*: e28cca.* add ip, ip, #.* ; 0x.* .*: e5bcf.* ldr pc, \[ip, #.*\]! + .*: e28fc6.* add ip, pc, #.* ; 0x.* + .*: e28cca.* add ip, ip, #.* ; 0x.* + .*: e5bcf.* ldr pc, \[ip, #.*\]! Disassembly of section .text: .* : .*: e1a0c00d mov ip, sp .*: e92dd800 push {fp, ip, lr, pc} .*: ebfffff. bl .* + .*: 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 .* : + .*: f000 e80c blx 100030c <__app_func_from_thumb> + .*: f000 e804 blx 1000300 <__app_func_weak_from_thumb> .*: 4770 bx lr .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) .*: 46c0 nop \(mov r8, r8\) + +.* <__app_func_weak_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 1000308 <__app_func_weak_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: feffffb4 .word 0xfeffffb4 + +.* <__app_func_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 1000314 <__app_func_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: feffff9c .word 0xfeffff9c + ... + +.* : + .*: f000 e80c blx 200033c <__app_func_from_thumb> + .*: f000 e804 blx 2000330 <__app_func_weak_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\) + +.* <__app_func_weak_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 2000338 <__app_func_weak_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: fdffff84 .word 0xfdffff84 + +.* <__app_func_from_thumb>: + .*: e59fc000 ldr ip, \[pc, #0\] ; 2000344 <__app_func_from_thumb\+0x8> + .*: e08ff00c add pc, pc, ip + .*: fdffff6c .word 0xfdffff6c + ... diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib1.s b/ld/testsuite/ld-arm/farcall-mixed-lib1.s new file mode 100644 index 0000000000..a64c0bbbb5 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-lib1.s @@ -0,0 +1,31 @@ +@ Create a large shared library so that calls through PLT to an undef +@ symbol require insertion of a long branch stub. +@ Check also calls to an undef weak symbol. + + .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_func + .weak app_func_weak + bl app_func_weak + 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_func + bl app_func_weak + bx lr + .size lib_func2, . - lib_func2 diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib2.s b/ld/testsuite/ld-arm/farcall-mixed-lib2.s new file mode 100644 index 0000000000..cd5a71f527 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-lib2.s @@ -0,0 +1,19 @@ +@ Create a large shared library so that calls through PLT to an undef +@ symbol require insertion of a long branch stub. +@ Check also calls to an undef weak symbol. + + .text + .arch armv5t + + .space 0x1000000 + .p2align 4 + .globl lib_func3 + .type lib_func3, %function + .thumb_func + .code 16 +lib_func3: + bl app_func + .weak app_func_weak + bl app_func_weak + bx lr + .size lib_func3, . - lib_func3