This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: ARM/thumb interworking confuses unwinder
- From: Christophe LYON <christophe dot lyon at st dot com>
- To: binutils at sourceware dot org
- Date: Tue, 26 Aug 2008 11:13:32 +0200
- Subject: Re: ARM/thumb interworking confuses unwinder
- References: <4887E088.3050401@eCosCentric.com> <48887952.5090801@st.com> <48887B21.3070804@eCosCentric.com> <20080724130500.GA23244@caradoc.them.org> <489AF5D7.5070608@st.com> <20080811225226.GA18939@caradoc.them.org>
Hi,
I have a question. Have you tried any of the Thumb stubs on a
big-endian target? I worry that your trick of using a 32-bit
word with two 16-bit Thumb instructions in it is going to leave them
in the wrong order.
No, I didn't try, and was worrying about this too.
> Space before the *, not afterwards, please.
Here is an updated patch.
+ " first occurrence: %B: thumb call to arm"),
"Thumb", "ARM".
I changed this too. Note that I merely cut&pasted the error message from
another part of elf32-arm.c :-)
I also removed the reformated comments (Thumb->(non-interworking aware)
ARM), as they have been updated by Nick.
Otherwise OK; the big-endian question isn't new with this patch.
Can someone commit this for me? (as an only occasional contributor, I
still don't dare to request an account)
Thanks,
Christophe.
2008-08-07 Christophe Lyon <christophe.lyon@st.com>
bfd/
* elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define.
(elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch.
(arm_type_of_stub): Handle armv4t short branches. Update
prototype.
(arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch.
(arm_build_one_stub): Likewise.
(arm_size_one_stub): Likewise.
(elf32_arm_size_stubs): Use new arm_type_of_stub prototype.
(arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch.
ld/testsuite/
* ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
* ld-arm/farcall-group2.s: Fix comment.
* ld-arm/farcall-thumb-arm-short.d: New test.
* ld-arm/farcall-thumb-arm-short.s: New test.
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/bfd/elf32-arm.c binutils-cvs/src/bfd/elf32-arm.c
--- binutils-cvs-ref/src/bfd/elf32-arm.c 2008-08-26 10:56:04.000000000 +0200
+++ binutils-cvs/src/bfd/elf32-arm.c 2008-08-26 10:51:51.000000000 +0200
@@ -2045,6 +2045,13 @@
0x00000000, /* dcd R_ARM_ABS32(X) */
};
+static const bfd_vma arm_thumb_arm_v4t_short_branch_stub[] =
+ {
+ 0x46c04778, /* bx pc */
+ /* nop */
+ 0xea000000, /* b (X) */
+ };
+
static const bfd_vma arm_pic_long_branch_stub[] =
{
0xe59fc000, /* ldr r12, [pc] */
@@ -2063,6 +2070,7 @@
arm_thumb_v4t_stub_long_branch,
arm_thumb_thumb_stub_long_branch,
arm_thumb_arm_v4t_stub_long_branch,
+ arm_thumb_arm_v4t_stub_short_branch,
arm_stub_pic_long_branch,
};
@@ -2738,6 +2746,7 @@
{
case arm_thumb_thumb_stub_long_branch:
case arm_thumb_arm_v4t_stub_long_branch:
+ case arm_thumb_arm_v4t_stub_short_branch:
return TRUE;
case arm_stub_none:
BFD_FAIL ();
@@ -2756,7 +2765,10 @@
const Elf_Internal_Rela *rel,
unsigned char st_type,
struct elf32_arm_link_hash_entry *hash,
- bfd_vma destination)
+ bfd_vma destination,
+ asection *sym_sec,
+ bfd *input_bfd,
+ const char *name)
{
bfd_vma location;
bfd_signed_vma branch_offset;
@@ -2826,6 +2838,16 @@
else
{
/* Thumb to arm. */
+ if (sym_sec != NULL
+ && sym_sec->owner != NULL
+ && !INTERWORK_FLAG (sym_sec->owner))
+ {
+ (*_bfd_error_handler)
+ (_("%B(%s): warning: interworking not enabled.\n"
+ " first occurrence: %B: Thumb call to ARM"),
+ sym_sec->owner, input_bfd, name);
+ }
+
stub_type = (info->shared | globals->pic_veneer)
? ((globals->use_blx)
? arm_stub_pic_long_branch
@@ -2833,6 +2855,13 @@
: (globals->use_blx)
? arm_stub_long_branch
: arm_thumb_arm_v4t_stub_long_branch;
+
+ /* Handle v4t short branches */
+ if ( (stub_type == arm_thumb_arm_v4t_stub_long_branch)
+ && (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET)
+ && (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET)) {
+ stub_type = arm_thumb_arm_v4t_stub_short_branch;
+ }
}
}
}
@@ -2841,6 +2870,17 @@
if (st_type == STT_ARM_TFUNC)
{
/* Arm to thumb. */
+
+ if (sym_sec != NULL
+ && sym_sec->owner != NULL
+ && !INTERWORK_FLAG (sym_sec->owner))
+ {
+ (*_bfd_error_handler)
+ (_("%B(%s): warning: interworking not enabled.\n"
+ " first occurrence: %B: Thumb call to ARM"),
+ sym_sec->owner, input_bfd, name);
+ }
+
/* We have an extra 2-bytes reach because of the mode change
(bit 24 (H) of BLX encoding). */
if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
@@ -3098,6 +3138,10 @@
template = arm_thumb_arm_v4t_long_branch_stub;
template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
break;
+ case arm_thumb_arm_v4t_stub_short_branch:
+ template = arm_thumb_arm_v4t_short_branch_stub;
+ template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+ break;
case arm_stub_pic_long_branch:
template = arm_pic_long_branch_stub;
template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3147,6 +3191,19 @@
stub_bfd, stub_sec, stub_sec->contents,
stub_entry->stub_offset + 16, sym_value, 0);
break;
+ case arm_thumb_arm_v4t_stub_short_branch:
+ {
+ long int rel_offset;
+ static const insn32 t2a3_b_insn = 0xea000000;
+
+ rel_offset = sym_value - (stub_addr + 8 + 4);
+
+ put_arm_insn (globals, stub_bfd,
+ (bfd_vma) t2a3_b_insn | ((rel_offset >> 2) & 0x00FFFFFF),
+ loc + 4);
+ }
+ break;
+
case arm_stub_pic_long_branch:
/* We want the value relative to the address 8 bytes from the
start of the stub. */
@@ -3197,6 +3254,10 @@
template = arm_thumb_arm_v4t_long_branch_stub;
template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
break;
+ case arm_thumb_arm_v4t_stub_short_branch:
+ template = arm_thumb_arm_v4t_short_branch_stub;
+ template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+ break;
case arm_stub_pic_long_branch:
template = arm_pic_long_branch_stub;
template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3603,7 +3664,8 @@
/* Determine what (if any) linker stub is needed. */
stub_type = arm_type_of_stub (info, section, irela, st_type,
- hash, destination);
+ hash, destination, sym_sec,
+ input_bfd, sym_name);
if (stub_type == arm_stub_none)
continue;
@@ -11205,6 +11267,12 @@
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
return FALSE;
break;
+ case arm_thumb_arm_v4t_stub_short_branch:
+ if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
+ return FALSE;
+ if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
+ return FALSE;
+ break;
case arm_stub_pic_long_branch:
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
return FALSE;
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/arm-elf.exp binutils-cvs/src/ld/testsuite/ld-arm/arm-elf.exp
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/arm-elf.exp 2008-07-18 22:49:12.000000000 +0200
+++ binutils-cvs/src/ld/testsuite/ld-arm/arm-elf.exp 2008-08-07 14:46:24.000000000 +0200
@@ -207,7 +207,7 @@
{"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" {thumb2-bl.s}
{{objdump -dr thumb2-bl.d}}
"thumb2-bl"}
-
+
{"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s}
{{objdump -d armv4-bx.d}}
"armv4-bx"}
@@ -260,6 +260,9 @@
{"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 (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"}
{"Thumb-ARM farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
{{objdump -d farcall-thumb-arm-blx.d}}
"farcall-thumb-arm-blx"}
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-group2.s binutils-cvs/src/ld/testsuite/ld-arm/farcall-group2.s
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-group2.s 2008-05-23 16:16:16.000000000 +0200
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-group2.s 2008-08-07 10:48:15.000000000 +0200
@@ -1,10 +1,7 @@
-
@ Test to ensure that ARM calls exceeding 32Mb generate stubs.
-@ We will place the section .foo at 0x2000.
-
.text
-myfunc:
+myfunc:
bl bar3
bl bar4
bl bar5
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d 1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d 2008-08-06 13:48:05.000000000 +0200
@@ -0,0 +1,14 @@
+.*: file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+ 1000: 4778 bx pc
+ 1002: 46c0 nop \(mov r8, r8\)
+ 1004: ea000402 b 2014 <bar>
+00001008 <_start>:
+ 1008: f7ff fffa bl 1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+00002014 <bar>:
+ 2014: e12fff1e bx lr
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s 1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s 2008-08-06 13:38:48.000000000 +0200
@@ -0,0 +1,21 @@
+@ Test to ensure that a Thumb to ARM call within 4Mb does not generate a stub.
+
+ .global _start
+ .syntax unified
+
+@ We will place the section .text at 0x1000.
+
+ .text
+ .thumb_func
+_start:
+ bl bar
+
+@ We will place the section .foo at 0x2014.
+
+ .section .foo, "xa"
+
+ .arm
+ .type bar, %function
+bar:
+ bx lr
+