This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]