This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
ARM long branch stubs: be8
- From: Christophe LYON <christophe dot lyon at st dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Mon, 23 Feb 2009 12:40:18 +0100
- Subject: ARM long branch stubs: be8
Hi all,
Following our recent discussion, I propose the attached patch to fix
big-endian / be8 stubs encoding issues.
I am not particularly proud of the way it's now done, but it does the job.
In short, the Thumb instructions in the stubs now use 1 entry per
instruction (instead of 2 instr per entry), but this implies that the
encoding functions know the exact layout of each stub, so it makes
maintenance a bit more painful (I added some comments to warn about that).
I have added one more test (farcall-thumb-arm-be8).
Once this is OK, I'll come back to my original patches to improve
PIC/PLT support.
Christophe.
2009-02-20 Christophe Lyon <christophe.lyon@st.com>
bfd/
* elf32-arm.c (elf32_arm_stub_long_branch_thumb_only): Split Thumb
instructions encoding.
(elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise.
(elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise.
(arm_build_one_stub): Encode Arm and Thumb instructions separately
to take endianness into account.
(arm_size_one_stub): Hardcode size of stubs.
testsuite/
* ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test.
* ld-arm/farcall-thumb-arm-be8.d: New expected result.
* ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.172
diff -u -p -r1.172 elf32-arm.c
--- bfd/elf32-arm.c 18 Feb 2009 16:56:37 -0000 1.172
+++ bfd/elf32-arm.c 23 Feb 2009 09:50:07 -0000
@@ -2010,6 +2010,9 @@ static const bfd_vma elf32_arm_symbian_p
#define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
+/* CAUTION: when updating the stubs code, don't forget to also update
+ arm_build_one_stub and arm_size_one_stub below. */
+
/* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
to reach the stub if necessary. */
static const bfd_vma elf32_arm_stub_long_branch_any_any[] =
@@ -2032,12 +2035,12 @@ static const bfd_vma elf32_arm_stub_long
to ARM. */
static const bfd_vma elf32_arm_stub_long_branch_thumb_only[] =
{
- 0x4e02b540, /* push {r6, lr} */
- /* ldr r6, [pc, #8] */
- 0x473046fe, /* mov lr, pc */
- /* bx r6 */
- 0xbf00bd40, /* pop {r6, pc} */
- /* nop */
+ 0xb540, /* push {r6, lr} */
+ 0x4e02, /* ldr r6, [pc, #8] */
+ 0x46fe, /* mov lr, pc */
+ 0x4730, /* bx r6 */
+ 0xbd40, /* pop {r6, pc} */
+ 0xbf00, /* nop */
0x00000000, /* dcd R_ARM_ABS32(X) */
};
@@ -2045,10 +2048,10 @@ static const bfd_vma elf32_arm_stub_long
available. */
static const bfd_vma elf32_arm_stub_long_branch_v4t_thumb_arm[] =
{
- 0x4e03b540, /* push {r6, lr} */
- /* ldr r6, [pc, #12] */
- 0x473046fe, /* mov lr, pc */
- /* bx r6 */
+ 0xb540, /* push {r6, lr} */
+ 0x4e03, /* ldr r6, [pc, #12] */
+ 0x46fe, /* mov lr, pc */
+ 0x4730, /* bx r6 */
0xe8bd4040, /* pop {r6, pc} */
0xe12fff1e, /* bx lr */
0x00000000, /* dcd R_ARM_ABS32(X) */
@@ -2058,8 +2061,8 @@ static const bfd_vma elf32_arm_stub_long
one, when the destination is close enough. */
static const bfd_vma elf32_arm_stub_short_branch_v4t_thumb_arm[] =
{
- 0x46c04778, /* bx pc */
- /* nop */
+ 0x4778, /* bx pc */
+ 0x46c0, /* nop */
0xea000000, /* b (X) */
};
@@ -3089,8 +3092,7 @@ arm_build_one_stub (struct bfd_hash_entr
bfd_vma stub_addr;
bfd_byte *loc;
bfd_vma sym_value;
- int template_size;
- int size;
+ int size = 0;
const bfd_vma *template;
int i;
struct elf32_arm_link_hash_table * globals;
@@ -3119,49 +3121,85 @@ arm_build_one_stub (struct bfd_hash_entr
+ stub_entry->target_section->output_offset
+ stub_entry->target_section->output_section->vma);
+ /* CAUTION: the calls to put_arm_insn, put_thumb_insn and bfd_put_32
+ below must be kept in sync with the actual stubs contents. */
switch (stub_entry->stub_type)
{
case arm_stub_long_branch_any_any:
template = elf32_arm_stub_long_branch_any_any;
- template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 1; i++)
+ {
+ put_arm_insn (globals, stub_bfd, template[i], loc + size);
+ size += 4;
+ }
+ bfd_put_32 (stub_bfd, template[i], loc + size);
+ size += 4;
break;
+
case arm_stub_long_branch_v4t_arm_thumb:
template = elf32_arm_stub_long_branch_v4t_arm_thumb;
- template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 2; i++)
+ {
+ put_arm_insn (globals, stub_bfd, template[i], loc + size);
+ size += 4;
+ }
+ bfd_put_32 (stub_bfd, template[i], loc + size);
+ size += 4;
break;
+
case arm_stub_long_branch_thumb_only:
template = elf32_arm_stub_long_branch_thumb_only;
- template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 6; i++)
+ {
+ put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+ size += 2;
+ }
+ bfd_put_32 (stub_bfd, template[i], loc + size);
+ size += 4;
break;
+
case arm_stub_long_branch_v4t_thumb_arm:
template = elf32_arm_stub_long_branch_v4t_thumb_arm;
- template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 4; i++)
+ {
+ put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+ size += 2;
+ }
+ for (i = 4; i < 6; i++)
+ {
+ put_arm_insn (globals, stub_bfd, template[i], loc + size);
+ size += 4;
+ }
+ bfd_put_32 (stub_bfd, template[i], loc + size);
+ size += 4;
break;
+
case arm_stub_short_branch_v4t_thumb_arm:
template = elf32_arm_stub_short_branch_v4t_thumb_arm;
- template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 2; i++)
+ {
+ put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+ size += 2;
+ }
+ size += 4;
break;
+
case arm_stub_long_branch_any_any_pic:
template = elf32_arm_stub_long_branch_any_any_pic;
- template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+ for (i = 0; i < 2; i++)
+ {
+ put_arm_insn (globals, stub_bfd, template[i], loc + size);
+ size += 4;
+ }
+ bfd_put_32 (stub_bfd, template[i], loc + size);
+ size += 4;
break;
+
default:
BFD_FAIL ();
return FALSE;
}
- size = 0;
- for (i = 0; i < (template_size / 4); i++)
- {
- /* A 0 pattern is a placeholder, every other pattern is an
- instruction. */
- if (template[i] != 0)
- put_arm_insn (globals, stub_bfd, template[i], loc + size);
- else
- bfd_put_32 (stub_bfd, template[i], loc + size);
-
- size += 4;
- }
stub_sec->size += size;
/* Destination is Thumb. Force bit 0 to 1 to reflect this. */
@@ -3229,38 +3267,38 @@ arm_size_one_stub (struct bfd_hash_entry
struct elf32_arm_link_hash_table *htab;
const bfd_vma *template;
int template_size;
- int size;
- int i;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
htab = (struct elf32_arm_link_hash_table *) in_arg;
+ /* CAUTION: the stub sizes below must be kept in sync with the
+ actual stubs contents. */
switch (stub_entry->stub_type)
{
case arm_stub_long_branch_any_any:
template = elf32_arm_stub_long_branch_any_any;
- template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
+ template_size = 8;
break;
case arm_stub_long_branch_v4t_arm_thumb:
template = elf32_arm_stub_long_branch_v4t_arm_thumb;
- template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
+ template_size = 12;
break;
case arm_stub_long_branch_thumb_only:
template = elf32_arm_stub_long_branch_thumb_only;
- template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
+ template_size = 16;
break;
case arm_stub_long_branch_v4t_thumb_arm:
template = elf32_arm_stub_long_branch_v4t_thumb_arm;
- template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+ template_size = 20;
break;
case arm_stub_short_branch_v4t_thumb_arm:
template = elf32_arm_stub_short_branch_v4t_thumb_arm;
- template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+ template_size = 8;
break;
case arm_stub_long_branch_any_any_pic:
template = elf32_arm_stub_long_branch_any_any_pic;
- template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+ template_size = 12;
break;
default:
BFD_FAIL ();
@@ -3268,11 +3306,8 @@ arm_size_one_stub (struct bfd_hash_entry
break;
}
- size = 0;
- for (i = 0; i < (template_size / 4); i++)
- size += 4;
- size = (size + 7) & ~7;
- stub_entry->stub_sec->size += size;
+ template_size = (template_size + 7) & ~7;
+ stub_entry->stub_sec->size += template_size;
return TRUE;
}
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.44
diff -u -p -r1.44 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 5 Feb 2009 21:54:43 -0000 1.44
+++ ld/testsuite/ld-arm/arm-elf.exp 23 Feb 2009 09:50:13 -0000
@@ -284,6 +284,9 @@ set armeabitests {
{"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
{{objdump -d farcall-thumb-arm.d}}
"farcall-thumb-arm"}
+ {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
+ {{objdump -d farcall-thumb-arm-be8.d}}
+ "farcall-thumb-arm"}
{"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
{{objdump -d farcall-thumb-arm-short.d}}
"farcall-thumb-arm-short"}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-arm-arm-be8.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-arm-arm-be8.d
--- ld/testsuite/ld-arm/farcall-arm-arm-be8.d 25 Jun 2008 14:28:48 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-arm-arm-be8.d 23 Feb 2009 09:50:13 -0000
@@ -3,12 +3,12 @@
Disassembly of section .text:
00001000 <__bar_veneer>:
- 1000: 04f01fe5 .*
+ 1000: 04f01fe5 ldr pc, \[pc, #-4\] ; 1004 <__bar_veneer\+0x4>
1004: 02001020 .word 0x02001020
00001008 <_start>:
- 1008: fcffffeb .*
+ 1008: fcffffeb bl 1000 <__bar_veneer>
Disassembly of section .foo:
02001020 <bar>:
- 2001020: 1eff2fe1 .*
+ 2001020: 1eff2fe1 bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-thumb-arm-be8.d 23 Feb 2009 09:50:13 -0000
@@ -0,0 +1,20 @@
+.*: file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+ 1000: 40b5 push {r6, lr}
+ 1002: 034e ldr r6, \[pc, #12\] \(1010 <__bar_from_thumb\+0x10>\)
+ 1004: fe46 mov lr, pc
+ 1006: 3047 bx r6
+ 1008: 4040bde8 pop {r6, lr}
+ 100c: 1eff2fe1 bx lr
+ 1010: 02001014 .word 0x02001014
+ 1014: 00000000 .word 0x00000000
+
+00001018 <_start>:
+ 1018: fff7 f2ff bl 1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 1eff2fe1 bx lr