ARMv4-t TLS stub fix

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

ARMv4-t TLS stub fix

Paul Brook
The attached patch fixes a bug in the ARMv4t TLS call stubs.  We generate the
right kind of stub, then ignore this and splat a blx instruction in there
anyway.

The ST_BRANCH_TO_ARM isn't strictly necessary at this point (data symbols will
be marked ST_BRANCH_TO_ARM anyway), but that's going to change shortly.

I suspect someone was a bit naughty and created the testcases based on
observed output rather than expected results. The blx is clearly wrong.

Tested on arm-none-eabi
Applied to CVS head.

Paul

2011-05-31  Paul Brook  <[hidden email]>

        bfd/
        * elf32-arm.c (arm_stub_is_thumb): Add
        arm_stub_long_branch_v4t_thumb_tls_pic.
        (elf32_arm_final_link_relocate): TLS stubs are always ARM.
        Handle Thumb stubs.

        ld/testsuite/
        * ld-arm/tls-longplt.d: Update expected output.
        * ld-arm/tls-thumb1.d: Ditto.

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 671a209..611e08e 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3427,6 +3427,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
     case arm_stub_long_branch_v4t_thumb_arm:
     case arm_stub_short_branch_v4t_thumb_arm:
     case arm_stub_long_branch_v4t_thumb_arm_pic:
+    case arm_stub_long_branch_v4t_thumb_tls_pic:
     case arm_stub_long_branch_thumb_only_pic:
       return TRUE;
     case arm_stub_none:
@@ -9304,6 +9305,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
     || ELF32_R_TYPE(rel->r_info) == R_ARM_THM_TLS_CALL)
   {
     bfd_signed_vma offset;
+    /* TLS stubs are arm mode.  The original symbol is a
+       data object, so branch_type is bogus.  */
+    branch_type = ST_BRANCH_TO_ARM;
     enum elf32_arm_stub_type stub_type
       = arm_type_of_stub (info, input_section, rel,
   st_type, &branch_type,
@@ -9348,16 +9352,25 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
    input_section->output_offset
    + rel->r_offset + 4);
     
- /* Round up the offset to a word boundary */
- offset = (offset + 2) & ~2;
+ if (stub_type != arm_stub_none
+    && arm_stub_is_thumb (stub_type))
+  {
+    lower_insn = 0xd000;
+  }
+ else
+  {
+    lower_insn = 0xc000;
+    /* Round up the offset to a word boundary */
+    offset = (offset + 2) & ~2;
+  }
+
  neg = offset < 0;
  upper_insn = (0xf000
       | ((offset >> 12) & 0x3ff)
       | (neg << 10));
- lower_insn = (0xc000
-      | (((!((offset >> 23) & 1)) ^ neg) << 13)
+ lower_insn |= (((!((offset >> 23) & 1)) ^ neg) << 13)
       | (((!((offset >> 22) & 1)) ^ neg) << 11)
-      | ((offset >> 1) & 0x7ff));
+      | ((offset >> 1) & 0x7ff);
  bfd_put_16 (input_bfd, upper_insn, hit_data);
  bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
  return bfd_reloc_ok;
diff --git a/ld/testsuite/ld-arm/tls-longplt.d b/ld/testsuite/ld-arm/tls-longplt.d
index 8729e74..175c561 100644
--- a/ld/testsuite/ld-arm/tls-longplt.d
+++ b/ld/testsuite/ld-arm/tls-longplt.d
@@ -47,7 +47,7 @@ Disassembly of section .foo:
  4001018: e1a00000 nop ; .*
  400101c: fc00f2a0 .word 0xfc00f2a0
  4001020: 4801       ldr r0, \[pc, #4\] ; .*
- 4001022: f000 e80a blx 4001038 .*
+ 4001022: f000 f809 bl 4001038 .*
  4001026: 46c0       nop ; .*
  4001028: fc00f291 .word 0xfc00f291
  400102c: 00000000 .word 0x00000000
diff --git a/ld/testsuite/ld-arm/tls-thumb1.d b/ld/testsuite/ld-arm/tls-thumb1.d
index 26b65bb..ad2a512 100644
--- a/ld/testsuite/ld-arm/tls-thumb1.d
+++ b/ld/testsuite/ld-arm/tls-thumb1.d
@@ -31,7 +31,7 @@ Disassembly of section .text:
     81b0: e1a00000 nop ; .*
     81b4: 000080c0 .word 0x000080c0
     81b8: 4801       ldr r0, \[pc, #4\] ; .*
-    81ba: f000 e806 blx 81c8 .*
+    81ba: f000 f805 bl 81c8 .*
     81be: 46c0       nop ; .*
     81c0: 000080b1 .word 0x000080b1
     81c4: 00000000 .word 0x00000000
@@ -55,7 +55,7 @@ Disassembly of section .foo:
  4001018: e1a00000 nop ; .*
  400101c: fc00f260 .word 0xfc00f260
  4001020: 4801       ldr r0, \[pc, #4\] ; .*
- 4001022: f000 e80c blx 400103c .*
+ 4001022: f000 f80b bl 400103c .*
  4001026: 46c0       nop ; .*
  4001028: fc00f249 .word 0xfc00f249
  400102c: 00000000 .word 0x00000000