From: Christophe Lyon Date: Thu, 5 Mar 2009 17:28:21 +0000 (+0000) Subject: 2009-03-05 Christophe Lyon X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=5fa9e92f74b051a84c435688595c141456a5d9f3;p=deliverable%2Fbinutils-gdb.git 2009-03-05 Christophe Lyon bfd/ * elf32-arm.c (arm_type_of_stub): Handle long branches targetting PLT entries. (elf32_arm_final_link_relocate): Likewise. testsuite/ * ld-arm/arm-elf.exp: Add 2 more tests to check long branch stubs in PLT context. * ld-arm/farcall-mixed-app-v5.d: New file. * ld-arm/farcall-mixed-app.d: Likewise. * ld-arm/farcall-mixed-app.r: Likewise. * ld-arm/farcall-mixed-app.s: Likewise. * ld-arm/farcall-mixed-app.sym: Likewise. * ld-arm/farcall-mixed-lib.d: Likewise. * ld-arm/farcall-mixed-lib.r: Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 78a23a80f8..bc12f9f328 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2009-03-05 Christophe Lyon + + * elf32-arm.c (arm_type_of_stub): Handle long branches targetting + PLT entries. + (elf32_arm_final_link_relocate): Likewise. + 2009-03-05 Moritz Kroll PR 9923 diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 2527e5e842..607ba04ada 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2857,6 +2857,7 @@ arm_type_of_stub (struct bfd_link_info *info, int thumb2; int thumb_only; enum elf32_arm_stub_type stub_type = arm_stub_none; + int use_plt = 0; /* We don't know the actual type of destination in case it is of type STT_SECTION: give up. */ @@ -2878,20 +2879,38 @@ arm_type_of_stub (struct bfd_link_info *info, r_type = ELF32_R_TYPE (rel->r_info); - /* If the call will go through a PLT entry then we do not need - glue. */ + /* Keep a simpler condition, for the sake of clarity. */ if (globals->splt != NULL && hash != NULL && hash->root.plt.offset != (bfd_vma) -1) - return stub_type; + { + use_plt = 1; + /* Note when dealing with PLT entries: the main PLT stub is in + ARM mode, so if the branch is in Thumb mode, another + Thumb->ARM stub will be inserted later just before the ARM + PLT stub. We don't take this extra distance into account + here, because if a long branch stub is needed, we'll add a + Thumb->Arm one and branch directly to the ARM PLT entry + because it avoids spreading offset corrections in several + places. */ + } if (r_type == R_ARM_THM_CALL) { + /* Handle cases where: + - this call goes too far (different Thumb/Thumb2 max + distance) + - it's a Thumb->Arm call and blx is not available. A stub is + needed in this case, but only if this call is not through a + PLT entry. Indeed, PLT stubs handle mode switching already. + */ if ((!thumb2 && (branch_offset > THM_MAX_FWD_BRANCH_OFFSET || (branch_offset < THM_MAX_BWD_BRANCH_OFFSET))) || (thumb2 && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))) - || ((st_type != STT_ARM_TFUNC) && !globals->use_blx)) + || ((st_type != STT_ARM_TFUNC) + && ((r_type == R_ARM_THM_CALL) && !globals->use_blx) + && !use_plt)) { if (st_type == STT_ARM_TFUNC) { @@ -6049,9 +6068,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* Handle relocations which should use the PLT entry. ABS32/REL32 will use the symbol's value, which may point to a PLT entry, but we don't need to handle that here. If we created a PLT entry, all - branches in this object should go to it. */ + branches in this object should go to it, except if the PLT is too + far away, in which case a long branch stub should be inserted. */ if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32 - && r_type != R_ARM_ABS32_NOI && r_type != R_ARM_REL32_NOI) + && r_type != R_ARM_ABS32_NOI && r_type != R_ARM_REL32_NOI + && r_type != R_ARM_CALL) && h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1) @@ -6208,11 +6229,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, bfd_signed_vma branch_offset; struct elf32_arm_stub_hash_entry *stub_entry = NULL; - from = (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); - branch_offset = (bfd_signed_vma)(value - from); - if (r_type == R_ARM_XPC25) { /* Check for Arm calling Arm function. */ @@ -6244,6 +6260,21 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, destination is too far or we are changing mode. */ if (r_type == R_ARM_CALL) { + /* If the call goes through a PLT entry, make sure to + check distance to the right destination address. */ + if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1) + { + value = (splt->output_section->vma + + splt->output_offset + + h->plt.offset); + *unresolved_reloc_p = FALSE; + } + + from = (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); + branch_offset = (bfd_signed_vma)(value - from); + if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET || branch_offset < ARM_MAX_BWD_BRANCH_OFFSET || sym_flags == STT_ARM_TFUNC) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 60465f7e79..693a93bde9 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2009-03-05 Christophe Lyon + + * ld-arm/arm-elf.exp: Add 2 more tests to check long branch stubs + in PLT context. + * ld-arm/farcall-mixed-app-v5.d: New file. + * ld-arm/farcall-mixed-app.d: Likewise. + * ld-arm/farcall-mixed-app.r: Likewise. + * ld-arm/farcall-mixed-app.s: Likewise. + * ld-arm/farcall-mixed-app.sym: Likewise. + * ld-arm/farcall-mixed-lib.d: Likewise. + * ld-arm/farcall-mixed-lib.r: Likewise. + 2009-03-04 Alan Modra * ld-powerpc/tlsmark.s, * ld-powerpc/tlsmark.d: New test. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 48b2b51ea7..0dfc44188c 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -338,6 +338,17 @@ set armeabitests { {"Group size=2" "-Ttext 0x1000 --section-start .foo=0x2003020 --stub-group-size=2" "" {farcall-group.s farcall-group2.s} {{objdump -d farcall-group-size2.d}} "farcall-group-size2"} + + {"Mixed ARM/Thumb dynamic application with farcalls" "tmpdir/mixed-lib.so -T arm-dyn.ld --section-start .far_arm=0x2100000 --section-start .far_thumb=0x2200000" "" + {farcall-mixed-app.s} + {{objdump -fdw farcall-mixed-app.d} {objdump -Rw farcall-mixed-app.r} + {readelf -Ds farcall-mixed-app.sym}} + "farcall-mixed-app"} + {"Mixed ARM/Thumb arch5 dynamic application with farcalls" "tmpdir/mixed-lib.so -T arm-dyn.ld --use-blx --section-start .far_arm=0x2100000 --section-start .far_thumb=0x2200000" "" + {farcall-mixed-app.s} + {{objdump -fdw farcall-mixed-app-v5.d} {objdump -Rw farcall-mixed-app.r} + {readelf -Ds farcall-mixed-app.sym}} + "farcall-mixed-app-v5"} } run_ld_link_tests $armeabitests diff --git a/ld/testsuite/ld-arm/farcall-mixed-app-v5.d b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d new file mode 100644 index 0000000000..ba6c77deeb --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d @@ -0,0 +1,82 @@ + +tmpdir/farcall-mixed-app-v5: file format elf32-(little|big)arm +architecture: arm, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* <.plt>: + .*: e52de004 push {lr} ; \(str lr, \[sp, #-4\]!\) + .*: e59fe004 ldr lr, \[pc, #4\] ; .* <_start-0x1c> + .*: e08fe00e add lr, pc, lr + .*: e5bef008 ldr pc, \[lr, #8\]! + .*: .* + .*: 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: + +.* <_start>: + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000008 bl .* <__app_func_veneer> + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* : + .*: b500 push {lr} + .*: f7ff efe2 blx .* <_start-0x18> + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + +.* <__app_func_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__app_func_veneer\+0x4> + .*: 02100000 .word 0x02100000 + +Disassembly of section .far_arm: + +.* : + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000008 bl .* <__lib_func1_veneer> + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* : + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* <__lib_func1_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 2100034 <__lib_func1_veneer\+0x4> + .*: 00008224 .word 0x00008224 + +Disassembly of section .far_thumb: + +.* : + .*: b500 push {lr} + .*: f000 e806 blx .* <__lib_func2_from_thumb> + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + +.* <__lib_func2_from_thumb>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 2200014 <__lib_func2_from_thumb\+0x4> + .*: 00008218 .word 0x00008218 diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.d b/ld/testsuite/ld-arm/farcall-mixed-app.d new file mode 100644 index 0000000000..df565e6c96 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app.d @@ -0,0 +1,87 @@ + +tmpdir/farcall-mixed-app: file format elf32-(little|big)arm +architecture: arm, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* <.plt>: + .*: e52de004 push {lr} ; \(str lr, \[sp, #-4\]!\) + .*: e59fe004 ldr lr, \[pc, #4\] ; .* <_start-0x2c> + .*: e08fe00e add lr, pc, lr + .*: e5bef008 ldr pc, \[lr, #8\]! + .*: .* + .*: 4778 bx pc + .*: 46c0 nop \(mov r8, r8\) + .*: 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: + +.* <_start>: + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000008 bl .* <__app_func_veneer> + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* : + .*: b500 push {lr} + .*: f7ff ffd9 bl 8218 <_start-0x28> + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + +.* <__app_func_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 8274 <__app_func_veneer\+0x4> + .*: 02100000 .word 0x02100000 + +Disassembly of section .far_arm: + +.* : + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000008 bl .* <__lib_func1_veneer> + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* : + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* <__lib_func1_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 2100034 <__lib_func1_veneer\+0x4> + .*: 00008228 .word 0x00008228 + +Disassembly of section .far_thumb: + +.* : + .*: b500 push {lr} + .*: f000 f805 bl .* <__lib_func2_from_thumb> + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) + +.* <__lib_func2_from_thumb>: + .*: 4778 bx pc + .*: 46c0 nop \(mov r8, r8\) + .*: e51ff004 ldr pc, \[pc, #-4\] ; 2200018 <__lib_func2_from_thumb\+0x8> + .*: 0000821c .word 0x0000821c + .*: 00000000 .word 0x00000000 diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.r b/ld/testsuite/ld-arm/farcall-mixed-app.r new file mode 100644 index 0000000000..910a361ca4 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app.r @@ -0,0 +1,10 @@ + +tmpdir/farcall-mixed-app.*: file format elf32-(little|big)arm + +DYNAMIC RELOCATION RECORDS +OFFSET TYPE VALUE +.* R_ARM_COPY data_obj +.* R_ARM_JUMP_SLOT lib_func2 +.* R_ARM_JUMP_SLOT lib_func1 + + diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.s b/ld/testsuite/ld-arm/farcall-mixed-app.s new file mode 100644 index 0000000000..78d5f65209 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app.s @@ -0,0 +1,58 @@ + .text + .p2align 4 + .globl _start +_start: + mov ip, sp + stmdb sp!, {r11, ip, lr, pc} + bl app_func + ldmia sp, {r11, sp, lr} + bx lr + + .p2align 4 + .globl app_tfunc_close + .type app_tfunc_close,%function + .thumb_func + .code 16 +app_tfunc_close: + push {lr} + bl lib_func2 + pop {pc} + bx lr + +@ We will place the section .far_arm at 0x2100000. + .section .far_arm, "xa" + + .arm + .p2align 4 + .globl app_func + .type app_func,%function +app_func: + mov ip, sp + stmdb sp!, {r11, ip, lr, pc} + bl lib_func1 + ldmia sp, {r11, sp, lr} + bx lr + + .arm + .p2align 4 + .globl app_func2 + .type app_func2,%function +app_func2: + bx lr + +@ We will place the section .far_thumb at 0x2200000. + .section .far_thumb, "xa" + + .p2align 4 + .globl app_tfunc + .type app_tfunc,%function + .thumb_func + .code 16 +app_tfunc: + push {lr} + bl lib_func2 + pop {pc} + bx lr + + .data + .long data_obj diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.sym b/ld/testsuite/ld-arm/farcall-mixed-app.sym new file mode 100644 index 0000000000..657e38454b --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app.sym @@ -0,0 +1,17 @@ + +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _edata + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start__ + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _end + .. ..: ........ 4 OBJECT GLOBAL DEFAULT 12 data_obj + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_end__ + .. ..: 0*[^0]*.* 0 FUNC GLOBAL DEFAULT UND lib_func1 + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_start + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT 11 __data_start + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __end__ + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start + .. ..: .......0 0 FUNC GLOBAL DEFAULT 14 app_func2 + .. ..: 0*[^0]*.* 0 FUNC GLOBAL DEFAULT UND lib_func2 + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _bss_end__ + .. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_end diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib.d b/ld/testsuite/ld-arm/farcall-mixed-lib.d new file mode 100644 index 0000000000..ab498e4f9a --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-lib.d @@ -0,0 +1,37 @@ +tmpdir/farcall-mixed-lib.so: file format elf32-(little|big)arm +architecture: arm, flags 0x00000150: +HAS_SYMS, DYNAMIC, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* <.plt>: + .*: e52de004 push {lr} ; \(str lr, \[sp, #-4\]!\) + .*: e59fe004 ldr lr, \[pc, #4\] ; .* + .*: e08fe00e add lr, pc, lr + .*: e5bef008 ldr pc, \[lr, #8\]! + .*: .* + .*: 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 .* + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + .*: e1a00000 nop \(mov r0,r0\) + +.* : + .*: 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\) + .*: 46c0 nop \(mov r8, r8\) + .*: 46c0 nop \(mov r8, r8\) diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib.r b/ld/testsuite/ld-arm/farcall-mixed-lib.r new file mode 100644 index 0000000000..a44f83b35a --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-lib.r @@ -0,0 +1,8 @@ + +tmpdir/farcall-mixed-lib.so: file format elf32-(little|big)arm + +DYNAMIC RELOCATION RECORDS +OFFSET TYPE VALUE +.* R_ARM_JUMP_SLOT app_func2 + +