This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] Thumb-2 BL support for bfd
- From: Mark Shinwell <shinwell at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 24 Aug 2006 16:23:36 +0100
- Subject: [PATCH] Thumb-2 BL support for bfd
Hello,
Here is the necessary bfd support for the exploitation of the extra
offset available when dealing with Thumb-2 BL instructions. The
assembler does not require any further modifications to enable this
to be used, as can be seen from the testcases. (A colleague commented
earlier that the sources of some of the test cases are very similar, but
I'd prefer to keep them separate so as to not mix up dump tests and the
other ones with explicit rules in arm-elf.exp.)
Tested on arm-none-linux-gnueabi. OK?
Mark
--
2006-08-24 Mark Shinwell <shinwell@codesourcery.com>
bfd/
* elf32-arm.c (elf32_arm_howto_table_1): Change offset for
R_THM_CALL to 25 and remove FIXME comment.
(using_thumb2): New function.
(elf32_arm_final_link_relocate): Cope with Thumb-2 BL encoding.
ld/testsuite/
* arm-elf.exp: Add thumb1-bl, thumb2-bl, thumb2-bl-as-thumb1-bad
and thumb2-bl-bad tests.
* thumb1-bl.d: New.
* thumb1-bl.s: New.
* thumb2-bl-as-thumb1-bad.d: New.
* thumb2-bl-as-thumb1-bad.s: New.
* thumb2-bl-bad.d: New.
* thumb2-bl-bad.s: New.
* thumb2-bl.d: New.
* thumb2-bl.s: New.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.87
diff -U3 -p -r1.87 elf32-arm.c
--- bfd/elf32-arm.c 22 Aug 2006 13:18:03 -0000 1.87
+++ bfd/elf32-arm.c 24 Aug 2006 15:05:41 -0000
@@ -217,11 +217,10 @@ static reloc_howto_type elf32_arm_howto_
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* FIXME: Has two more bits of offset in Thumb32. */
HOWTO (R_ARM_THM_CALL, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 23, /* bitsize */
+ 25, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
@@ -3534,6 +3533,14 @@ identify_add_or_sub(bfd_vma insn)
return 0;
}
+/* Determine if we're dealing with a Thumb-2 object. */
+
+static int using_thumb2 (struct elf32_arm_link_hash_table *globals)
+{
+ int arch = elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch);
+ return arch == 8 || arch >= 10;
+}
+
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
@@ -3950,22 +3957,33 @@ elf32_arm_final_link_relocate (reloc_how
/* Thumb BL (branch long instruction). */
{
bfd_vma relocation;
+ bfd_vma reloc_sign;
bfd_boolean overflow = FALSE;
bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
- bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
- bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+ bfd_signed_vma reloc_signed_max;
+ bfd_signed_vma reloc_signed_min;
bfd_vma check;
bfd_signed_vma signed_check;
+ int bitsize;
+ int thumb2 = using_thumb2 (globals);
- /* Need to refetch the addend and squish the two 11 bit pieces
- together. */
+ /* Fetch the addend. We use the Thumb-2 encoding (backwards compatible
+ with Thumb-1) involving the J1 and J2 bits. */
if (globals->use_rel)
{
- bfd_vma upper = upper_insn & 0x7ff;
- bfd_vma lower = lower_insn & 0x7ff;
- upper = (upper ^ 0x400) - 0x400; /* Sign extend. */
- addend = (upper << 12) | (lower << 1);
+ bfd_vma s = (upper_insn & (1 << 10)) >> 10;
+ bfd_vma upper = upper_insn & 0x3ff;
+ bfd_vma lower = lower_insn & 0x7ff;
+ bfd_vma j1 = (lower_insn & (1 << 13)) >> 13;
+ bfd_vma j2 = (lower_insn & (1 << 11)) >> 11;
+ bfd_vma i1 = j1 ^ s ? 0 : 1;
+ bfd_vma i2 = j2 ^ s ? 0 : 1;
+
+ addend = (i1 << 23) | (i2 << 22) | (upper << 12) | (lower << 1);
+ /* Sign extend. */
+ addend = (addend | ((s ? 0 : 1) << 24)) - (1 << 24);
+
signed_addend = addend;
}
@@ -4042,6 +4060,15 @@ elf32_arm_final_link_relocate (reloc_how
else
signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
+ /* Calculate the permissable maximum and minimum values for
+ this relocation according to whether we're relocating for
+ Thumb-2 or not. */
+ bitsize = howto->bitsize;
+ if (!thumb2)
+ bitsize -= 2;
+ reloc_signed_max = ((1 << (bitsize - 1)) - 1) >> howto->rightshift;
+ reloc_signed_min = ~reloc_signed_max;
+
/* Assumes two's complement. */
if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
overflow = TRUE;
@@ -4053,9 +4080,17 @@ elf32_arm_final_link_relocate (reloc_how
1 of the base address. */
relocation = (relocation + 2) & ~ 3;
- /* Put RELOCATION back into the insn. */
- upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
- lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
+ /* Put RELOCATION back into the insn. Assumes two's complement.
+ We use the Thumb-2 encoding, which is safe even if dealing with
+ a Thumb-1 instruction by virtue of our overflow check above. */
+ reloc_sign = (signed_check < 0) ? 1 : 0;
+ upper_insn = (upper_insn & ~(bfd_vma) 0x7ff)
+ | ((relocation >> 12) & 0x3ff)
+ | (reloc_sign << 10);
+ lower_insn = (lower_insn & ~(bfd_vma) 0x2fff)
+ | (((!((relocation >> 23) & 1)) ^ reloc_sign) << 13)
+ | (((!((relocation >> 22) & 1)) ^ reloc_sign) << 11)
+ | ((relocation >> 1) & 0x7ff);
/* Put the relocated value back in the object file: */
bfd_put_16 (input_bfd, upper_insn, hit_data);
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.17
diff -U3 -p -r1.17 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 18 Aug 2006 15:00:18 -0000 1.17
+++ ld/testsuite/ld-arm/arm-elf.exp 24 Aug 2006 15:05:43 -0000
@@ -62,6 +62,12 @@ set armelftests {
{"Group relocations" "-Ttext 0x8000 --section-start zero=0x0 --section-start alpha=0xeef0 --section-start beta=0xffeef0" "" {group-relocs.s}
{{objdump -Dr group-relocs.d}}
"group-relocs"}
+ {"Thumb-1 BL" "-Ttext 0x1000 --section-start .foo=0x401000" "" {thumb1-bl.s}
+ {{objdump -dr thumb1-bl.d}}
+ "thumb1-bl"}
+ {"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" {thumb2-bl.s}
+ {{objdump -dr thumb2-bl.d}}
+ "thumb2-bl"}
{"Simple non-PIC shared library" "-shared" "" {arm-lib.s}
{{objdump -fdw arm-lib.d} {objdump -Rw arm-lib.r}}
"arm-lib.so"}
@@ -146,4 +152,6 @@ run_dump_test "group-relocs-alu-bad"
run_dump_test "group-relocs-ldr-bad"
run_dump_test "group-relocs-ldrs-bad"
run_dump_test "group-relocs-ldc-bad"
+run_dump_test "thumb2-bl-as-thumb1-bad"
+run_dump_test "thumb2-bl-bad"
#name: Thumb-2 BL failure test
#source: thumb2-bl-bad.s
#ld: -Ttext 0x1000 --section-start .foo=0x1001004
#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
@ Test to ensure that a Thumb-2 BL works with an offset that is
@ not permissable for Thumb-1.
.arch armv7
.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 0x1001000.
.section .foo, "xa"
.thumb_func
bar:
bx lr
.*thumb2-bl: file format elf32-.*arm
Disassembly of section .text:
00001000 <_start>:
1000: f3ff d7fe bl 1001000 <bar>
Disassembly of section .foo:
01001000 <bar>:
1001000: 4770 bx lr
.*thumb1-bl: file format elf32-.*arm
Disassembly of section .text:
00001000 <_start>:
1000: f3ff fffe bl 401000 <bar>
Disassembly of section .foo:
00401000 <bar>:
401000: 4770 bx lr
@ Test to ensure that a Thumb-2 BL with an oversize offset fails.
.arch armv7
.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 0x1001004.
.section .foo, "xa"
.thumb_func
bar:
bx lr
@ Test to ensure that a Thumb-1 BL with a Thumb-2-only offset fails.
.arch armv5t
.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 0x401004.
.section .foo, "xa"
.thumb_func
bar:
bx lr
#name: Thumb-2-as-Thumb-1 BL failure test
#source: thumb2-bl-as-thumb1-bad.s
#ld: -Ttext 0x1000 --section-start .foo=0x401004
#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
@ Test to ensure that a Thumb-1 BL works.
.arch armv5t
.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 0x401000.
.section .foo, "xa"
.thumb_func
bar:
bx lr