This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
ARM long branch stubs: PLT
- From: Christophe LYON <christophe dot lyon at st dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Fri, 27 Feb 2009 17:12:46 +0100
- Subject: ARM long branch stubs: PLT
Hi all,
I propose here one more step in the long branch stubs story: handle long
branches toward PLT entries.
Once this patch is accepted, I will propose one more to handle JUMP24
and PLT32 relocations (eg to support tail-call compiler optimizations).
Christophe.
2009-02-27 Christophe Lyon <christophe.lyon@st.com>
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.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.178
diff -u -p -r1.178 elf32-arm.c
--- bfd/elf32-arm.c 26 Feb 2009 15:37:52 -0000 1.178
+++ bfd/elf32-arm.c 27 Feb 2009 16:09:24 -0000
@@ -2857,6 +2857,7 @@ arm_type_of_stub (struct bfd_link_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 *
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_how
/* 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_how
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_how
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)
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.49
diff -u -p -r1.49 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 26 Feb 2009 15:37:53 -0000 1.49
+++ ld/testsuite/ld-arm/arm-elf.exp 27 Feb 2009 16:09:31 -0000
@@ -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
Index: ld/testsuite/ld-arm/farcall-mixed-app-v5.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-app-v5.d
diff -N ld/testsuite/ld-arm/farcall-mixed-app-v5.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-app-v5.d 27 Feb 2009 16:09:31 -0000
@@ -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\)
+
+.* <app_tfunc_close>:
+ .*: 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:
+
+.* <app_func>:
+ .*: 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\)
+
+.* <app_func2>:
+ .*: 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:
+
+.* <app_tfunc>:
+ .*: 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
Index: ld/testsuite/ld-arm/farcall-mixed-app.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-app.d
diff -N ld/testsuite/ld-arm/farcall-mixed-app.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-app.d 27 Feb 2009 16:09:31 -0000
@@ -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\)
+
+.* <app_tfunc_close>:
+ .*: 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:
+
+.* <app_func>:
+ .*: 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\)
+
+.* <app_func2>:
+ .*: 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:
+
+.* <app_tfunc>:
+ .*: 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
Index: ld/testsuite/ld-arm/farcall-mixed-app.r
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-app.r
diff -N ld/testsuite/ld-arm/farcall-mixed-app.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-app.r 27 Feb 2009 16:09:31 -0000
@@ -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
+
+
Index: ld/testsuite/ld-arm/farcall-mixed-app.s
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-app.s
diff -N ld/testsuite/ld-arm/farcall-mixed-app.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-app.s 27 Feb 2009 16:09:31 -0000
@@ -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
Index: ld/testsuite/ld-arm/farcall-mixed-app.sym
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-app.sym
diff -N ld/testsuite/ld-arm/farcall-mixed-app.sym
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-app.sym 27 Feb 2009 16:09:31 -0000
@@ -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
Index: ld/testsuite/ld-arm/farcall-mixed-lib.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-lib.d
diff -N ld/testsuite/ld-arm/farcall-mixed-lib.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-lib.d 27 Feb 2009 16:09:31 -0000
@@ -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\] ; .* <lib_func1-0x.*>
+ .*: 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:
+
+.* <lib_func1>:
+ .*: e1a0c00d mov ip, sp
+ .*: e92dd800 push {fp, ip, lr, pc}
+ .*: ebfffff. bl .* <lib_func1-0x..?>
+ .*: e89d6800 ldm sp, {fp, sp, lr}
+ .*: e12fff1e bx lr
+ .*: e1a00000 nop \(mov r0,r0\)
+ .*: e1a00000 nop \(mov r0,r0\)
+ .*: e1a00000 nop \(mov r0,r0\)
+
+.* <lib_func2>:
+ .*: 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\)
Index: ld/testsuite/ld-arm/farcall-mixed-lib.r
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-mixed-lib.r
diff -N ld/testsuite/ld-arm/farcall-mixed-lib.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-mixed-lib.r 27 Feb 2009 16:09:31 -0000
@@ -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
+
+