This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Long call support broke Thumb veneers
- From: Christophe LYON <christophe dot lyon at st dot com>
- To: binutils at sourceware dot org
- Date: Tue, 03 Jun 2008 19:06:53 +0200
- Subject: Re: Long call support broke Thumb veneers
- References: <20080603135443.GA11132@caradoc.them.org>
Daniel,
On 03.06.2008 15:54, Daniel Jacobowitz wrote:
Christophe, you removed handling of two relocation types from
bfd_elf32_arm_process_before_allocation, which is responsible for
inserting these stubs. How do you intend they be handled?
record_arm_to_thumb_glue is now never called for them.
In general, handling long call stubs differently from mode-changing
stubs seems like asking for trouble.
Well,
While taking into account Paul's remarks, it seemed clearer to me to
handle mode-switching stubs in the same place as long calls (ie a call
which involves mode-switching is handled by the stubs I added, whatever
the distance).
Unfortunately I forgot to handle this case in elf32_arm_final_link_relocate.
I propose the attached patch, which also fixes another issue (BLX was
still used in cases where it shouldn't). I ran the testsuite with
arm-none-eabi and arm-elf targets.
I checked with the code fragment you mentioned (using Code Sourcery
2008q1-126 release), it seems OK to me but I am worrying about your
generic-hosted.ld linker script: indeed, the long call stubs are
generated before __cs3_interrupt_vector, and I suspect this is problem,
isn't it?
Christophe.
2008-06-03 Christophe Lyon <christophe.lyon@st.com>
bfd/
* elf32-arm.c (arm_stub_is_thumb): Define.
(elf32_arm_final_link_relocate): Handle near mode switching stubs.
ld/testsuite/
* ld-arm/farcall-thumb-thumb-m.d: Fix branch type.
* ld-arm/farcall-thumb-arm.d: Likewise.
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-m.d
===================================================================
--- ld/testsuite/ld-arm/farcall-thumb-thumb-m.d (revision 680)
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-m.d (working copy)
@@ -12,7 +12,7 @@ Disassembly of section .text:
100c: 02001015 .word 0x02001015
00001010 <_start>:
- 1010: f7ff eff6 blx 1000 <_start-0x10>
+ 1010: f7ff fff6 bl 1000 <_start-0x10>
Disassembly of section .foo:
02001014 <bar>:
Index: ld/testsuite/ld-arm/farcall-thumb-arm.d
===================================================================
--- ld/testsuite/ld-arm/farcall-thumb-arm.d (revision 747)
+++ ld/testsuite/ld-arm/farcall-thumb-arm.d (working copy)
@@ -12,7 +12,7 @@ Disassembly of section .text:
...
00001018 <_start>:
- 1018: f7ff eff2 blx 1000 <_start-0x18>
+ 1018: f7ff fff2 bl 1000 <_start-0x18>
Disassembly of section .foo:
02001014 <bar>:
Index: bfd/elf32-arm.c
===================================================================
--- bfd/elf32-arm.c (revision 747)
+++ bfd/elf32-arm.c (working copy)
@@ -2680,6 +2680,21 @@ elf32_arm_hash_table_free (struct bfd_li
static int using_thumb2 (struct elf32_arm_link_hash_table *globals);
static int using_thumb_only (struct elf32_arm_link_hash_table *globals);
+static bfd_boolean arm_stub_is_thumb(enum elf32_arm_stub_type stub_type)
+{
+ switch(stub_type) {
+ case arm_thumb_thumb_stub_long_branch:
+ case arm_thumb_arm_v4t_stub_long_branch:
+ return TRUE;
+ case arm_stub_none:
+ BFD_FAIL ();
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
static enum elf32_arm_stub_type
arm_type_of_stub (struct bfd_link_info *info,
asection *input_sec,
@@ -6306,6 +6321,7 @@ elf32_arm_final_link_relocate (reloc_how
(branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))
)
+ || ((sym_flags != STT_ARM_TFUNC) && !globals->use_blx)
)
{
/* The target is out of reach or we are changing modes, so
@@ -6320,10 +6336,14 @@ elf32_arm_final_link_relocate (reloc_how
+ stub_entry->stub_sec->output_offset
+ stub_entry->stub_sec->output_section->vma);
- /* This call becomes a call to Arm for sure. Force BLX */
+ /* If this call becomes a call to Arm, force BLX */
+ if (globals->use_blx) {
+ if ( (stub_entry && !arm_stub_is_thumb(stub_entry->stub_type))
+ || (sym_flags != STT_ARM_TFUNC) )
lower_insn = (lower_insn & ~0x1000) | 0x0800;
}
}
+ }
relocation = value + signed_addend;