bfd/
authorMark Shinwell <shinwell@codesourcery.com>
Thu, 24 Aug 2006 14:49:52 +0000 (14:49 +0000)
committerMark Shinwell <shinwell@codesourcery.com>
Thu, 24 Aug 2006 14:49:52 +0000 (14:49 +0000)
* 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.

ChangeLog.csl
bfd/elf32-arm.c
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/thumb1-bl.d [new file with mode: 0644]
ld/testsuite/ld-arm/thumb1-bl.s [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl-bad.d [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl-bad.s [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl.d [new file with mode: 0644]
ld/testsuite/ld-arm/thumb2-bl.s [new file with mode: 0644]

index f6dd8cd..a351202 100644 (file)
@@ -1,6 +1,26 @@
 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.
+
+2006-08-24  Mark Shinwell  <shinwell@codesourcery.com>
+
+       bfd/
        * elf32-arm.c (elf32_arm_final_link_relocate): Add cases
        for R_ARM_ABS32_NOI and R_ARM_REL32_NOI.
        (elf32_arm_gc_sweep_hook): Likewise.
index d91d2a1..9ae60fd 100644 (file)
@@ -217,11 +217,10 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         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 */
@@ -3527,6 +3526,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
@@ -3956,22 +3963,33 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       /* 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;
          }
 
@@ -4048,6 +4066,15 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        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;
@@ -4059,9 +4086,17 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
             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 eee3204..af94c87 100644 (file)
@@ -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"
 
diff --git a/ld/testsuite/ld-arm/thumb1-bl.d b/ld/testsuite/ld-arm/thumb1-bl.d
new file mode 100644 (file)
index 0000000..09d7095
--- /dev/null
@@ -0,0 +1,11 @@
+
+.*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
diff --git a/ld/testsuite/ld-arm/thumb1-bl.s b/ld/testsuite/ld-arm/thumb1-bl.s
new file mode 100644 (file)
index 0000000..cdecaa4
--- /dev/null
@@ -0,0 +1,22 @@
+@ 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
+
diff --git a/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d
new file mode 100644 (file)
index 0000000..749b58f
--- /dev/null
@@ -0,0 +1,4 @@
+#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'
diff --git a/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s
new file mode 100644 (file)
index 0000000..dae5d43
--- /dev/null
@@ -0,0 +1,22 @@
+@ 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
+
diff --git a/ld/testsuite/ld-arm/thumb2-bl-bad.d b/ld/testsuite/ld-arm/thumb2-bl-bad.d
new file mode 100644 (file)
index 0000000..0fc6e04
--- /dev/null
@@ -0,0 +1,4 @@
+#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'
diff --git a/ld/testsuite/ld-arm/thumb2-bl-bad.s b/ld/testsuite/ld-arm/thumb2-bl-bad.s
new file mode 100644 (file)
index 0000000..63e3fe7
--- /dev/null
@@ -0,0 +1,22 @@
+@ 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
+
diff --git a/ld/testsuite/ld-arm/thumb2-bl.d b/ld/testsuite/ld-arm/thumb2-bl.d
new file mode 100644 (file)
index 0000000..bdfb9b7
--- /dev/null
@@ -0,0 +1,11 @@
+
+.*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
diff --git a/ld/testsuite/ld-arm/thumb2-bl.s b/ld/testsuite/ld-arm/thumb2-bl.s
new file mode 100644 (file)
index 0000000..ddb1cd3
--- /dev/null
@@ -0,0 +1,23 @@
+@ 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
+