ARM long branch stubs: pic take 2

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

ARM long branch stubs: pic take 2

Christophe Lyon
Hi all,

I am continuing the submission in small pieces of my original big patch
(http://sourceware.org/ml/binutils/2009-02/msg00041.html). I think that
I will submit 2 more patches in the coming days.

Here I propose 3 new stubs to handle PIC cases which were so far
unsupported.

I suspect the stub code will need careful review again :-)

Christophe.

2009-02-25  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New
        stub.
        (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise.
        (elf32_arm_stub_long_branch_thumb_only_pic): Likewise.
        (elf32_arm_stub_type): Add new enum entries for the new stubs.
        (arm_stub_is_thumb): Catch new stubs.
        (arm_type_of_stub): Handle new stubs.
        (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs.
        (bfd_elf32_arm_process_before_allocation): Remove useless
        condition.

        testsuite/
        * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs.
        * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the
        test is now expected to pass.
        * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise.
        * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.177
diff -u -p -r1.177 elf32-arm.c
--- bfd/elf32-arm.c 24 Feb 2009 22:44:18 -0000 1.177
+++ bfd/elf32-arm.c 25 Feb 2009 15:19:13 -0000
@@ -2110,6 +2110,40 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
   };
 
+/* V4T ARM -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
+  {
+    ARM_INSN(0xe59fc004),             /* ldr   ip, [pc, #4] */
+    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
+    ARM_INSN(0xe12fff1c),             /* bx    ip */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
+  };
+
+/* V4T Thumb -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
+  {
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop  */
+    ARM_INSN(0xe59fc004),             /* ldr  ip, [pc, #4] */
+    ARM_INSN(0xe08cc00f),             /* add  ip, ip, pc */
+    ARM_INSN(0xe1a0f00c),             /* mov  pc, ip */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
+  };
+
+/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
+   support only this mode, or on V4T where it is expensive to switch
+   to ARM.  */
+static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
+  {
+    THUMB16_INSN(0xb401),             /* push {r0} */
+    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
+    THUMB16_INSN(0x46fc),             /* mov  ip, pc */
+    THUMB16_INSN(0x4484),             /* add  ip, r0 */
+    THUMB16_INSN(0xbc01),             /* pop  {r0} */
+    THUMB16_INSN(0x4760),             /* bx   ip */
+    DATA_WORD(0, R_ARM_REL32, 2),     /* dcd  R_ARM_REL32(X) */
+  };
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -2124,6 +2158,9 @@ enum elf32_arm_stub_type
   arm_stub_short_branch_v4t_thumb_arm,
   arm_stub_long_branch_any_arm_pic,
   arm_stub_long_branch_any_thumb_pic,
+  arm_stub_long_branch_v4t_arm_thumb_pic,
+  arm_stub_long_branch_v4t_thumb_arm_pic,
+  arm_stub_long_branch_thumb_only_pic,
 };
 
 struct elf32_arm_stub_hash_entry
@@ -2796,6 +2833,8 @@ arm_stub_is_thumb (enum elf32_arm_stub_t
     case arm_stub_long_branch_thumb_only:
     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_thumb_only_pic:
       return TRUE;
     case arm_stub_none:
       BFD_FAIL ();
@@ -2872,8 +2911,8 @@ arm_type_of_stub (struct bfd_link_info *
     ? ((globals->use_blx)
        /* V5T and above.  */
        ? arm_stub_long_branch_any_thumb_pic
-       /* not yet supported on V4T.  */
-       : arm_stub_none)
+       /* On V4T, use Thumb code only.  */
+       : arm_stub_long_branch_thumb_only_pic)
 
     /* non-PIC stubs.  */
     : ((globals->use_blx)
@@ -2885,8 +2924,8 @@ arm_type_of_stub (struct bfd_link_info *
       else
  {
   stub_type = (info->shared | globals->pic_veneer)
-    /* PIC stub not yet supported on V4T.  */
-    ? arm_stub_none
+    /* PIC stub.  */
+    ? arm_stub_long_branch_thumb_only_pic
     /* non-PIC stub.  */
     : arm_stub_long_branch_thumb_only;
  }
@@ -2909,8 +2948,8 @@ arm_type_of_stub (struct bfd_link_info *
  ? ((globals->use_blx)
    /* V5T and above.  */
    ? arm_stub_long_branch_any_arm_pic
-   /* not yet supported on V4T.  */
-   : arm_stub_none)
+   /* V4T PIC stub.  */
+   : arm_stub_long_branch_v4t_thumb_arm_pic)
 
  /* non-PIC stubs.  */
  : ((globals->use_blx)
@@ -2951,7 +2990,12 @@ arm_type_of_stub (struct bfd_link_info *
     {
       stub_type = (info->shared | globals->pic_veneer)
  /* PIC stubs.  */
- ? arm_stub_long_branch_any_thumb_pic
+ ? ((globals->use_blx)
+   /* V5T and above.  */
+   ? arm_stub_long_branch_any_thumb_pic
+   /* V4T stub.  */
+   : arm_stub_long_branch_v4t_arm_thumb_pic)
+
  /* non-PIC stubs.  */
  : ((globals->use_blx)
    /* V5T and above.  */
@@ -3271,32 +3315,43 @@ arm_size_one_stub (struct bfd_hash_entry
     {
     case arm_stub_long_branch_any_any:
       template =  elf32_arm_stub_long_branch_any_any;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
-
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_any);
       break;
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb);
       break;
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only);
       break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm);
       break;
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_short_branch_v4t_thumb_arm);
       break;
     case arm_stub_long_branch_any_arm_pic:
       template = elf32_arm_stub_long_branch_any_arm_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_arm_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_arm_pic);
       break;
     case arm_stub_long_branch_any_thumb_pic:
       template = elf32_arm_stub_long_branch_any_thumb_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_thumb_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+      template = elf32_arm_stub_long_branch_v4t_arm_thumb_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+      template = elf32_arm_stub_long_branch_v4t_thumb_arm_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm_pic);
+      break;
+    case arm_stub_long_branch_thumb_only_pic:
+      template = elf32_arm_stub_long_branch_thumb_only_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic);
       break;
     default:
       BFD_FAIL ();
@@ -4647,8 +4702,7 @@ bfd_elf32_arm_process_before_allocation
       /* This one is a call from arm code.  We need to look up
          the target of the call.  If it is a thumb target, we
          insert glue.  */
-      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
-  && !(r_type == R_ARM_CALL && globals->use_blx))
+      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
  record_arm_to_thumb_glue (link_info, h);
       break;
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.48
diff -u -p -r1.48 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 24 Feb 2009 22:43:10 -0000 1.48
+++ ld/testsuite/ld-arm/arm-elf.exp 25 Feb 2009 15:19:20 -0000
@@ -296,6 +296,12 @@ set armeabitests {
     {"Thumb-Thumb farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s}
      {{objdump -d farcall-thumb-thumb-blx-pic-veneer.d}}
      "farcall-thumb-thumb-blx-pic-veneer"}
+    {"Thumb-Thumb farcall M profile (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv7m" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-m-pic-veneer.d}}
+     "farcall-thumb-thumb-m-pic-veneer"}
+    {"Thumb-Thumb farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv4t" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-pic-veneer.d}}
+     "farcall-thumb-thumb-pic-veneer"}
 
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
@@ -315,6 +321,9 @@ set armeabitests {
     {"Thumb-ARM farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-blx-pic-veneer.d}}
      "farcall-thumb-arm-blx-pic-veneer"}
+    {"Thumb-ARM farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-pic-veneer.d}}
+     "farcall-thumb-arm-pic-veneer"}
 
     {"Multiple farcalls" "-Ttext 0x1000 --section-start .foo=0x2002020" "" {farcall-mix.s}
      {{objdump -d farcall-mix.d}}
@@ -350,9 +359,6 @@ run_dump_test "attr-merge-wchar-24-nowar
 run_dump_test "attr-merge-wchar-40-nowarn"
 run_dump_test "attr-merge-wchar-42-nowarn"
 run_dump_test "attr-merge-wchar-44-nowarn"
-run_dump_test "farcall-thumb-thumb-pic-veneer"
-run_dump_test "farcall-thumb-thumb-m-pic-veneer"
-run_dump_test "farcall-thumb-arm-pic-veneer"
 run_dump_test "farcall-section"
 run_dump_test "attr-merge-unknown-1"
 run_dump_test "attr-merge-unknown-2"
Index: ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-arm-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 25 Feb 2009 15:19:20 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-ARM farcall without BLX (PIC veneer)
-#source: farcall-thumb-arm.s
-#as: -march=armv4t -W
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_from_thumb>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_from_thumb>:
+    1008: 4778       bx pc
+    100a: 46c0       nop \(mov r8, r8\)
+    100c: e59fc004 ldr ip, \[pc, #4\] ; 1018 <__bar_from_thumb\+0x10>
+    1010: e08cc00f add ip, ip, pc
+    1014: e1a0f00c mov pc, ip
+    1018: 01fffffc .word 0x01fffffc
+    101c: 00000000 .word 0x00000000
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: e12fff1e bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-m-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 25 Feb 2009 15:19:20 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall M profile (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000003 .word 0x02000003
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 25 Feb 2009 15:19:20 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall without BLX (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000003 .word 0x02000003
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Richard Earnshaw
On Wed, 2009-02-25 at 16:21 +0100, Christophe LYON wrote:

> +/* V4T Thumb -> ARM long branch stub, PIC.  */
> +static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
> +  {
> +    THUMB16_INSN(0x4778),             /* bx   pc */
> +    THUMB16_INSN(0x46c0),             /* nop  */
> +    ARM_INSN(0xe59fc004),             /* ldr  ip, [pc, #4] */
> +    ARM_INSN(0xe08cc00f),             /* add  ip, ip, pc */
> +    ARM_INSN(0xe1a0f00c),             /* mov  pc, ip */
> +    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
> +  };

We can do slightly better than that:

        .thumb
        bx pc
        nop
        .arm
        ldr ip, [pc, #0]
        add pc, pc, ip
        dcd R_ARM_REL32(X)

Which is OK because we know the target address is ARM.

R.

Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon
On 25.02.2009 18:33, Richard Earnshaw wrote:

> We can do slightly better than that:

Thanks. I have updated my patch accordingly.
In addition to the previous one, I have removed a useless enum type
(stub_reloc_type) and renamed the reloc_type field of insn_sequence to
r_type to have the same name as usually used in other parts.

Christophe.

2009-02-25  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (stub_reloc_type): Removed.
        (insn_sequence): Renamed reloc_type field to r_type.
        (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New stub.
        (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise.
        (elf32_arm_stub_long_branch_thumb_only_pic): Likewise.
        (elf32_arm_stub_type): Add new enum entries for the new stubs.
        (arm_stub_is_thumb): Catch new stubs.
        (arm_type_of_stub): Handle new stubs.
        (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs.
        (bfd_elf32_arm_process_before_allocation): Remove useless
        condition.

        testsuite/
        * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs.
        * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the
        test is now expected to pass.
        * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise.
        * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.177
diff -u -p -r1.177 elf32-arm.c
--- bfd/elf32-arm.c 24 Feb 2009 22:44:18 -0000 1.177
+++ bfd/elf32-arm.c 25 Feb 2009 17:47:22 -0000
@@ -2018,13 +2018,6 @@ enum stub_insn_type
     DATA_TYPE
   };
 
-enum stub_reloc_type
-  {
-    STUB_RELOC_NONE = 0,
-    STUB_RELOC_ABS,
-    STUB_RELOC_PIC,
-  };
-
 #define THUMB16_INSN(X)    {(X), THUMB16_TYPE, R_ARM_NONE, 0}
 #define THUMB32_INSN(X)    {(X), THUMB32_TYPE, R_ARM_NONE, 0}
 #define ARM_INSN(X)        {(X), ARM_TYPE, R_ARM_NONE, 0}
@@ -2035,7 +2028,7 @@ typedef struct
 {
   bfd_vma data;
   enum stub_insn_type type;
-  enum stub_reloc_type reloc_type;
+  unsigned int r_type;
   int reloc_addend;
 }  insn_sequence;
 
@@ -2110,6 +2103,39 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
   };
 
+/* V4T ARM -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
+  {
+    ARM_INSN(0xe59fc004),             /* ldr   ip, [pc, #4] */
+    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
+    ARM_INSN(0xe12fff1c),             /* bx    ip */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
+  };
+
+/* V4T Thumb -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
+  {
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop  */
+    ARM_INSN(0xe59fc000),             /* ldr  ip, [pc, #0] */
+    ARM_INSN(0xe08cf00f),             /* add  pc, ip, pc */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
+  };
+
+/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
+   support only this mode, or on V4T where it is expensive to switch
+   to ARM.  */
+static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
+  {
+    THUMB16_INSN(0xb401),             /* push {r0} */
+    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
+    THUMB16_INSN(0x46fc),             /* mov  ip, pc */
+    THUMB16_INSN(0x4484),             /* add  ip, r0 */
+    THUMB16_INSN(0xbc01),             /* pop  {r0} */
+    THUMB16_INSN(0x4760),             /* bx   ip */
+    DATA_WORD(0, R_ARM_REL32, 2),     /* dcd  R_ARM_REL32(X) */
+  };
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -2124,6 +2150,9 @@ enum elf32_arm_stub_type
   arm_stub_short_branch_v4t_thumb_arm,
   arm_stub_long_branch_any_arm_pic,
   arm_stub_long_branch_any_thumb_pic,
+  arm_stub_long_branch_v4t_arm_thumb_pic,
+  arm_stub_long_branch_v4t_thumb_arm_pic,
+  arm_stub_long_branch_thumb_only_pic,
 };
 
 struct elf32_arm_stub_hash_entry
@@ -2796,6 +2825,8 @@ arm_stub_is_thumb (enum elf32_arm_stub_t
     case arm_stub_long_branch_thumb_only:
     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_thumb_only_pic:
       return TRUE;
     case arm_stub_none:
       BFD_FAIL ();
@@ -2872,8 +2903,8 @@ arm_type_of_stub (struct bfd_link_info *
     ? ((globals->use_blx)
        /* V5T and above.  */
        ? arm_stub_long_branch_any_thumb_pic
-       /* not yet supported on V4T.  */
-       : arm_stub_none)
+       /* On V4T, use Thumb code only.  */
+       : arm_stub_long_branch_thumb_only_pic)
 
     /* non-PIC stubs.  */
     : ((globals->use_blx)
@@ -2885,8 +2916,8 @@ arm_type_of_stub (struct bfd_link_info *
       else
  {
   stub_type = (info->shared | globals->pic_veneer)
-    /* PIC stub not yet supported on V4T.  */
-    ? arm_stub_none
+    /* PIC stub.  */
+    ? arm_stub_long_branch_thumb_only_pic
     /* non-PIC stub.  */
     : arm_stub_long_branch_thumb_only;
  }
@@ -2909,8 +2940,8 @@ arm_type_of_stub (struct bfd_link_info *
  ? ((globals->use_blx)
    /* V5T and above.  */
    ? arm_stub_long_branch_any_arm_pic
-   /* not yet supported on V4T.  */
-   : arm_stub_none)
+   /* V4T PIC stub.  */
+   : arm_stub_long_branch_v4t_thumb_arm_pic)
 
  /* non-PIC stubs.  */
  : ((globals->use_blx)
@@ -2951,7 +2982,12 @@ arm_type_of_stub (struct bfd_link_info *
     {
       stub_type = (info->shared | globals->pic_veneer)
  /* PIC stubs.  */
- ? arm_stub_long_branch_any_thumb_pic
+ ? ((globals->use_blx)
+   /* V5T and above.  */
+   ? arm_stub_long_branch_any_thumb_pic
+   /* V4T stub.  */
+   : arm_stub_long_branch_v4t_arm_thumb_pic)
+
  /* non-PIC stubs.  */
  : ((globals->use_blx)
    /* V5T and above.  */
@@ -3207,7 +3243,7 @@ arm_build_one_stub (struct bfd_hash_entr
   put_arm_insn (globals, stub_bfd, template[i].data, loc + size);
   /* Handle cases where the target is encoded within the
      instruction.  */
-  if (template[i].reloc_type == R_ARM_JUMP24)
+  if (template[i].r_type == R_ARM_JUMP24)
     {
       stub_reloc_idx = i;
       stub_reloc_offset = size;
@@ -3241,7 +3277,7 @@ arm_build_one_stub (struct bfd_hash_entr
   /* Assume there is one and only one entry to relocate in each stub.  */
   BFD_ASSERT (stub_reloc_idx != -1);
 
-  _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].reloc_type),
+  _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].r_type),
     stub_bfd, stub_sec, stub_sec->contents,
     stub_entry->stub_offset + stub_reloc_offset,
     sym_value, template[stub_reloc_idx].reloc_addend);
@@ -3271,32 +3307,43 @@ arm_size_one_stub (struct bfd_hash_entry
     {
     case arm_stub_long_branch_any_any:
       template =  elf32_arm_stub_long_branch_any_any;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
-
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_any);
       break;
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb);
       break;
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only);
       break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm);
       break;
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_short_branch_v4t_thumb_arm);
       break;
     case arm_stub_long_branch_any_arm_pic:
       template = elf32_arm_stub_long_branch_any_arm_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_arm_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_arm_pic);
       break;
     case arm_stub_long_branch_any_thumb_pic:
       template = elf32_arm_stub_long_branch_any_thumb_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_thumb_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+      template = elf32_arm_stub_long_branch_v4t_arm_thumb_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+      template = elf32_arm_stub_long_branch_v4t_thumb_arm_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm_pic);
+      break;
+    case arm_stub_long_branch_thumb_only_pic:
+      template = elf32_arm_stub_long_branch_thumb_only_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic);
       break;
     default:
       BFD_FAIL ();
@@ -4647,8 +4694,7 @@ bfd_elf32_arm_process_before_allocation
       /* This one is a call from arm code.  We need to look up
          the target of the call.  If it is a thumb target, we
          insert glue.  */
-      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
-  && !(r_type == R_ARM_CALL && globals->use_blx))
+      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
  record_arm_to_thumb_glue (link_info, h);
       break;
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.48
diff -u -p -r1.48 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 24 Feb 2009 22:43:10 -0000 1.48
+++ ld/testsuite/ld-arm/arm-elf.exp 25 Feb 2009 17:47:34 -0000
@@ -296,6 +296,12 @@ set armeabitests {
     {"Thumb-Thumb farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s}
      {{objdump -d farcall-thumb-thumb-blx-pic-veneer.d}}
      "farcall-thumb-thumb-blx-pic-veneer"}
+    {"Thumb-Thumb farcall M profile (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv7m" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-m-pic-veneer.d}}
+     "farcall-thumb-thumb-m-pic-veneer"}
+    {"Thumb-Thumb farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv4t" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-pic-veneer.d}}
+     "farcall-thumb-thumb-pic-veneer"}
 
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
@@ -315,6 +321,9 @@ set armeabitests {
     {"Thumb-ARM farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-blx-pic-veneer.d}}
      "farcall-thumb-arm-blx-pic-veneer"}
+    {"Thumb-ARM farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-pic-veneer.d}}
+     "farcall-thumb-arm-pic-veneer"}
 
     {"Multiple farcalls" "-Ttext 0x1000 --section-start .foo=0x2002020" "" {farcall-mix.s}
      {{objdump -d farcall-mix.d}}
@@ -350,9 +359,6 @@ run_dump_test "attr-merge-wchar-24-nowar
 run_dump_test "attr-merge-wchar-40-nowarn"
 run_dump_test "attr-merge-wchar-42-nowarn"
 run_dump_test "attr-merge-wchar-44-nowarn"
-run_dump_test "farcall-thumb-thumb-pic-veneer"
-run_dump_test "farcall-thumb-thumb-m-pic-veneer"
-run_dump_test "farcall-thumb-arm-pic-veneer"
 run_dump_test "farcall-section"
 run_dump_test "attr-merge-unknown-1"
 run_dump_test "attr-merge-unknown-2"
Index: ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-arm-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 25 Feb 2009 17:47:34 -0000
@@ -1,5 +1,20 @@
-#name: Thumb-ARM farcall without BLX (PIC veneer)
-#source: farcall-thumb-arm.s
-#as: -march=armv4t -W
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_from_thumb>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_from_thumb>:
+    1008: 4778       bx pc
+    100a: 46c0       nop \(mov r8, r8\)
+    100c: e59fc000 ldr ip, \[pc, #0\] ; 1014 <__bar_from_thumb\+0xc>
+    1010: e08cf00f add pc, ip, pc
+    1014: 02000000 .word 0x02000000
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: e12fff1e bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-m-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 25 Feb 2009 17:47:34 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall M profile (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000003 .word 0x02000003
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 25 Feb 2009 17:47:34 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall without BLX (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000003 .word 0x02000003
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Richard Earnshaw
On Wed, 2009-02-25 at 18:51 +0100, Christophe LYON wrote:

> +00001000 <_start>:
> +    1000:      f000 f802       bl      1008 <__bar_from_thumb>
> +    1004:      0000            lsls    r0, r0, #0
> +       ...
> +
> +00001008 <__bar_from_thumb>:
> +    1008:      4778            bx      pc
> +    100a:      46c0            nop                     \(mov r8, r8\)
> +    100c:      e59fc000        ldr     ip, \[pc, #0\]  ; 1014
> <__bar_from_thumb\+0xc>
> +    1010:      e08cf00f        add     pc, ip, pc
> +    1014:      02000000        .word   0x02000000
> +
> +Disassembly of section .foo:
> +
> +02001014 <bar>:
> + 2001014:      e12fff1e        bx      lr

I think that this shows that the offset calculation is wrong:  The
offset needs to be based on the location of the instruction that uses
the PC -- in this case address 0x1010, with PC=0x1018 (since it's an ARM
instruction), so 0x1018 + 0x02000000 = 0x02001018, which is the
instruction after your bx lr instruction.

R.

Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon

> I think that this shows that the offset calculation is wrong:  The
> offset needs to be based on the location of the instruction that uses
> the PC -- in this case address 0x1010, with PC=0x1018 (since it's an ARM
> instruction), so 0x1018 + 0x02000000 = 0x02001018, which is the
> instruction after your bx lr instruction.
>

Good catch!
Here an updated patch, with updated offsets for
elf32_arm_stub_long_branch_v4t_thumb_arm_pic and
elf32_arm_stub_long_branch_thumb_only_pic (and updated expected results
farcall-thumb-arm-pic-veneer.d farcall-thumb-thumb-m-pic-veneer.d
farcall-thumb-thumb-pic-veneer.d)

Christophe.

2009-02-25  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (stub_reloc_type): Removed.
        (insn_sequence): Renamed reloc_type field to r_type.
        (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New stub.
        (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise.
        (elf32_arm_stub_long_branch_thumb_only_pic): Likewise.
        (elf32_arm_stub_type): Add new enum entries for the new stubs.
        (arm_stub_is_thumb): Catch new stubs.
        (arm_type_of_stub): Handle new stubs.
        (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs.
        (bfd_elf32_arm_process_before_allocation): Remove useless
        condition.

        testsuite/
        * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs.
        * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the
        test is now expected to pass.
        * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise.
        * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.177
diff -u -p -r1.177 elf32-arm.c
--- bfd/elf32-arm.c 24 Feb 2009 22:44:18 -0000 1.177
+++ bfd/elf32-arm.c 26 Feb 2009 11:51:21 -0000
@@ -2018,13 +2018,6 @@ enum stub_insn_type
     DATA_TYPE
   };
 
-enum stub_reloc_type
-  {
-    STUB_RELOC_NONE = 0,
-    STUB_RELOC_ABS,
-    STUB_RELOC_PIC,
-  };
-
 #define THUMB16_INSN(X)    {(X), THUMB16_TYPE, R_ARM_NONE, 0}
 #define THUMB32_INSN(X)    {(X), THUMB32_TYPE, R_ARM_NONE, 0}
 #define ARM_INSN(X)        {(X), ARM_TYPE, R_ARM_NONE, 0}
@@ -2035,7 +2028,7 @@ typedef struct
 {
   bfd_vma data;
   enum stub_insn_type type;
-  enum stub_reloc_type reloc_type;
+  unsigned int r_type;
   int reloc_addend;
 }  insn_sequence;
 
@@ -2110,6 +2103,39 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
   };
 
+/* V4T ARM -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
+  {
+    ARM_INSN(0xe59fc004),             /* ldr   ip, [pc, #4] */
+    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
+    ARM_INSN(0xe12fff1c),             /* bx    ip */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
+  };
+
+/* V4T Thumb -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
+  {
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop  */
+    ARM_INSN(0xe59fc000),             /* ldr  ip, [pc, #0] */
+    ARM_INSN(0xe08cf00f),             /* add  pc, ip, pc */
+    DATA_WORD(0, R_ARM_REL32, -4),     /* dcd  R_ARM_REL32(X) */
+  };
+
+/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
+   support only this mode, or on V4T where it is expensive to switch
+   to ARM.  */
+static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
+  {
+    THUMB16_INSN(0xb401),             /* push {r0} */
+    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
+    THUMB16_INSN(0x46fc),             /* mov  ip, pc */
+    THUMB16_INSN(0x4484),             /* add  ip, r0 */
+    THUMB16_INSN(0xbc01),             /* pop  {r0} */
+    THUMB16_INSN(0x4760),             /* bx   ip */
+    DATA_WORD(0, R_ARM_REL32, 4),     /* dcd  R_ARM_REL32(X) */
+  };
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -2124,6 +2150,9 @@ enum elf32_arm_stub_type
   arm_stub_short_branch_v4t_thumb_arm,
   arm_stub_long_branch_any_arm_pic,
   arm_stub_long_branch_any_thumb_pic,
+  arm_stub_long_branch_v4t_arm_thumb_pic,
+  arm_stub_long_branch_v4t_thumb_arm_pic,
+  arm_stub_long_branch_thumb_only_pic,
 };
 
 struct elf32_arm_stub_hash_entry
@@ -2796,6 +2825,8 @@ arm_stub_is_thumb (enum elf32_arm_stub_t
     case arm_stub_long_branch_thumb_only:
     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_thumb_only_pic:
       return TRUE;
     case arm_stub_none:
       BFD_FAIL ();
@@ -2872,8 +2903,8 @@ arm_type_of_stub (struct bfd_link_info *
     ? ((globals->use_blx)
        /* V5T and above.  */
        ? arm_stub_long_branch_any_thumb_pic
-       /* not yet supported on V4T.  */
-       : arm_stub_none)
+       /* On V4T, use Thumb code only.  */
+       : arm_stub_long_branch_thumb_only_pic)
 
     /* non-PIC stubs.  */
     : ((globals->use_blx)
@@ -2885,8 +2916,8 @@ arm_type_of_stub (struct bfd_link_info *
       else
  {
   stub_type = (info->shared | globals->pic_veneer)
-    /* PIC stub not yet supported on V4T.  */
-    ? arm_stub_none
+    /* PIC stub.  */
+    ? arm_stub_long_branch_thumb_only_pic
     /* non-PIC stub.  */
     : arm_stub_long_branch_thumb_only;
  }
@@ -2909,8 +2940,8 @@ arm_type_of_stub (struct bfd_link_info *
  ? ((globals->use_blx)
    /* V5T and above.  */
    ? arm_stub_long_branch_any_arm_pic
-   /* not yet supported on V4T.  */
-   : arm_stub_none)
+   /* V4T PIC stub.  */
+   : arm_stub_long_branch_v4t_thumb_arm_pic)
 
  /* non-PIC stubs.  */
  : ((globals->use_blx)
@@ -2951,7 +2982,12 @@ arm_type_of_stub (struct bfd_link_info *
     {
       stub_type = (info->shared | globals->pic_veneer)
  /* PIC stubs.  */
- ? arm_stub_long_branch_any_thumb_pic
+ ? ((globals->use_blx)
+   /* V5T and above.  */
+   ? arm_stub_long_branch_any_thumb_pic
+   /* V4T stub.  */
+   : arm_stub_long_branch_v4t_arm_thumb_pic)
+
  /* non-PIC stubs.  */
  : ((globals->use_blx)
    /* V5T and above.  */
@@ -3207,7 +3243,7 @@ arm_build_one_stub (struct bfd_hash_entr
   put_arm_insn (globals, stub_bfd, template[i].data, loc + size);
   /* Handle cases where the target is encoded within the
      instruction.  */
-  if (template[i].reloc_type == R_ARM_JUMP24)
+  if (template[i].r_type == R_ARM_JUMP24)
     {
       stub_reloc_idx = i;
       stub_reloc_offset = size;
@@ -3241,7 +3277,7 @@ arm_build_one_stub (struct bfd_hash_entr
   /* Assume there is one and only one entry to relocate in each stub.  */
   BFD_ASSERT (stub_reloc_idx != -1);
 
-  _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].reloc_type),
+  _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].r_type),
     stub_bfd, stub_sec, stub_sec->contents,
     stub_entry->stub_offset + stub_reloc_offset,
     sym_value, template[stub_reloc_idx].reloc_addend);
@@ -3271,32 +3307,43 @@ arm_size_one_stub (struct bfd_hash_entry
     {
     case arm_stub_long_branch_any_any:
       template =  elf32_arm_stub_long_branch_any_any;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
-
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_any);
       break;
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb);
       break;
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only);
       break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm);
       break;
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_short_branch_v4t_thumb_arm);
       break;
     case arm_stub_long_branch_any_arm_pic:
       template = elf32_arm_stub_long_branch_any_arm_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_arm_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_arm_pic);
       break;
     case arm_stub_long_branch_any_thumb_pic:
       template = elf32_arm_stub_long_branch_any_thumb_pic;
-      template_size = sizeof (elf32_arm_stub_long_branch_any_thumb_pic) / sizeof (insn_sequence);
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+      template = elf32_arm_stub_long_branch_v4t_arm_thumb_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb_pic);
+      break;
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+      template = elf32_arm_stub_long_branch_v4t_thumb_arm_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm_pic);
+      break;
+    case arm_stub_long_branch_thumb_only_pic:
+      template = elf32_arm_stub_long_branch_thumb_only_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic);
       break;
     default:
       BFD_FAIL ();
@@ -4647,8 +4694,7 @@ bfd_elf32_arm_process_before_allocation
       /* This one is a call from arm code.  We need to look up
          the target of the call.  If it is a thumb target, we
          insert glue.  */
-      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
-  && !(r_type == R_ARM_CALL && globals->use_blx))
+      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
  record_arm_to_thumb_glue (link_info, h);
       break;
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.48
diff -u -p -r1.48 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 24 Feb 2009 22:43:10 -0000 1.48
+++ ld/testsuite/ld-arm/arm-elf.exp 26 Feb 2009 11:51:26 -0000
@@ -296,6 +296,12 @@ set armeabitests {
     {"Thumb-Thumb farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s}
      {{objdump -d farcall-thumb-thumb-blx-pic-veneer.d}}
      "farcall-thumb-thumb-blx-pic-veneer"}
+    {"Thumb-Thumb farcall M profile (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv7m" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-m-pic-veneer.d}}
+     "farcall-thumb-thumb-m-pic-veneer"}
+    {"Thumb-Thumb farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv4t" {farcall-thumb-thumb.s}
+     {{objdump -d farcall-thumb-thumb-pic-veneer.d}}
+     "farcall-thumb-thumb-pic-veneer"}
 
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
@@ -315,6 +321,9 @@ set armeabitests {
     {"Thumb-ARM farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-blx-pic-veneer.d}}
      "farcall-thumb-arm-blx-pic-veneer"}
+    {"Thumb-ARM farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-pic-veneer.d}}
+     "farcall-thumb-arm-pic-veneer"}
 
     {"Multiple farcalls" "-Ttext 0x1000 --section-start .foo=0x2002020" "" {farcall-mix.s}
      {{objdump -d farcall-mix.d}}
@@ -350,9 +359,6 @@ run_dump_test "attr-merge-wchar-24-nowar
 run_dump_test "attr-merge-wchar-40-nowarn"
 run_dump_test "attr-merge-wchar-42-nowarn"
 run_dump_test "attr-merge-wchar-44-nowarn"
-run_dump_test "farcall-thumb-thumb-pic-veneer"
-run_dump_test "farcall-thumb-thumb-m-pic-veneer"
-run_dump_test "farcall-thumb-arm-pic-veneer"
 run_dump_test "farcall-section"
 run_dump_test "attr-merge-unknown-1"
 run_dump_test "attr-merge-unknown-2"
Index: ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-arm-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d 26 Feb 2009 11:51:27 -0000
@@ -1,5 +1,20 @@
-#name: Thumb-ARM farcall without BLX (PIC veneer)
-#source: farcall-thumb-arm.s
-#as: -march=armv4t -W
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_from_thumb>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_from_thumb>:
+    1008: 4778       bx pc
+    100a: 46c0       nop \(mov r8, r8\)
+    100c: e59fc000 ldr ip, \[pc, #0\] ; 1014 <__bar_from_thumb\+0xc>
+    1010: e08cf00f add pc, ip, pc
+    1014: 01fffffc .word 0x01fffffc
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: e12fff1e bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-m-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d 26 Feb 2009 11:51:27 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall M profile (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000005 .word 0x02000005
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-thumb-thumb-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 23 Feb 2009 10:03:47 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 26 Feb 2009 11:51:27 -0000
@@ -1,5 +1,22 @@
-#name: Thumb-Thumb farcall without BLX (PIC veneer)
-#source: farcall-thumb-thumb.s
-#as: -march=armv4t
-#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar'
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <_start>:
+    1000: f000 f802 bl 1008 <__bar_veneer>
+    1004: 0000       lsls r0, r0, #0
+ ...
+
+00001008 <__bar_veneer>:
+    1008: b401       push {r0}
+    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
+    100c: 46fc       mov ip, pc
+    100e: 4484       add ip, r0
+    1010: bc01       pop {r0}
+    1012: 4760       bx ip
+    1014: 02000005 .word 0x02000005
+
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 4770       bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Richard Earnshaw
On Thu, 2009-02-26 at 12:55 +0100, Christophe LYON wrote:

> > I think that this shows that the offset calculation is wrong:  The
> > offset needs to be based on the location of the instruction that uses
> > the PC -- in this case address 0x1010, with PC=0x1018 (since it's an ARM
> > instruction), so 0x1018 + 0x02000000 = 0x02001018, which is the
> > instruction after your bx lr instruction.
> >
>
> Good catch!
> Here an updated patch, with updated offsets for
> elf32_arm_stub_long_branch_v4t_thumb_arm_pic and
> elf32_arm_stub_long_branch_thumb_only_pic (and updated expected results
> farcall-thumb-arm-pic-veneer.d farcall-thumb-thumb-m-pic-veneer.d
> farcall-thumb-thumb-pic-veneer.d)
>
> Christophe.
> plain text document attachment (pic2.changelog)
> 2009-02-25  Christophe Lyon  <[hidden email]>
>
> bfd/
> * elf32-arm.c (stub_reloc_type): Removed.
> (insn_sequence): Renamed reloc_type field to r_type.
> (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New stub.
> (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise.
> (elf32_arm_stub_long_branch_thumb_only_pic): Likewise.
> (elf32_arm_stub_type): Add new enum entries for the new stubs.
> (arm_stub_is_thumb): Catch new stubs.
> (arm_type_of_stub): Handle new stubs.
> (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs.
> (bfd_elf32_arm_process_before_allocation): Remove useless
> condition.
>
> testsuite/
> * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs.
> * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the
> test is now expected to pass.
> * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise.
> * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise.

Yes, I think this is OK now.  Daniel, you've reviewed most of this
series, do you have any final comments?

R.

Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Daniel Jacobowitz-3
On Thu, Feb 26, 2009 at 02:59:28PM +0000, Richard Earnshaw wrote:
> Yes, I think this is OK now.  Daniel, you've reviewed most of this
> series, do you have any final comments?

It looks good to me also.

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon
On 26.02.2009 16:06, Daniel Jacobowitz wrote:
> On Thu, Feb 26, 2009 at 02:59:28PM +0000, Richard Earnshaw wrote:
>> Yes, I think this is OK now.  Daniel, you've reviewed most of this
>> series, do you have any final comments?
>
> It looks good to me also.
>

Thanks to all of you!
Sorry for making the reviewers job so useful :-)

I commit this patch asap and prepare the next one.

Christophe.

Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Daniel Jacobowitz-2
On Thu, Feb 26, 2009 at 04:34:37PM +0100, Christophe LYON wrote:
> Thanks to all of you!
> Sorry for making the reviewers job so useful :-)

Thank you, too.  We're going through a couple of rough spots on these
patches - but they're very useful, and it's a worthwhile exercise on
all sides.

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Paul Brook
In reply to this post by Christophe Lyon
On Wednesday 25 February 2009, Christophe LYON wrote:
> +/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
> +   support only this mode, or on V4T where it is expensive to switch
> +   to ARM.  */
> +static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
> +  {
> +    THUMB16_INSN(0xb401),             /* push {r0} */

The EABI specifies that veneers may only use the stack on M profile devices
(i.e. when ARM mode is not available).

Paul
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon
On 26.02.2009 20:01, Paul Brook wrote:

> On Wednesday 25 February 2009, Christophe LYON wrote:
>> +/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
>> +   support only this mode, or on V4T where it is expensive to switch
>> +   to ARM.  */
>> +static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
>> +  {
>> +    THUMB16_INSN(0xb401),             /* push {r0} */
>
> The EABI specifies that veneers may only use the stack on M profile devices
> (i.e. when ARM mode is not available).
>

I have just updated my copy of EABI, and saw the sentence you are
referring to.

So this means that the sample code you provided in
http://sourceware.org/ml/binutils/2009-02/msg00224.html should also have
a variant for Thumb -> Thumb stub (pic and non-pic) on V4T.

I'll give a look at that.

Thanks

Christophe.
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon
Hello,

>> The EABI specifies that veneers may only use the stack on M profile
>> devices (i.e. when ARM mode is not available).
>>
>
> I have just updated my copy of EABI, and saw the sentence you are
> referring to.
>
> So this means that the sample code you provided in
> http://sourceware.org/ml/binutils/2009-02/msg00224.html should also have
> a variant for Thumb -> Thumb stub (pic and non-pic) on V4T.
>
> I'll give a look at that.
>
I propose a new patch that takes care of this issue.
I think the M-profile stubs could be improved; maybe for another patch?

Christophe.

2009-03-12  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (elf32_arm_stub_long_branch_v4t_thumb_thumb,
        elf32_arm_stub_long_branch_v4t_thumb_thumb_pic): Two new long
        branch stubs.
        (elf32_arm_stub_type): New enum values for the two new stubs.
        (arm_type_of_stub): Make use of the two new stubs.
        (arm_size_one_stub): Handle the two new stubs.

        testsuite/
        * ld-arm/farcall-thumb-thumb-pic-veneer.d: Update expected
        results.
        * ld-arm/farcall-thumb-thumb.d: Likewise.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.180
diff -u -p -r1.180 elf32-arm.c
--- bfd/elf32-arm.c 6 Mar 2009 08:57:57 -0000 1.180
+++ bfd/elf32-arm.c 12 Mar 2009 14:13:08 -0000
@@ -2049,9 +2049,7 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
   };
 
-/* Thumb -> Thumb long branch stub. Used on architectures which
-   support only this mode, or on V4T where it is expensive to switch
-   to ARM.  */
+/* Thumb -> Thumb long branch stub. Used on M-profile architectures.  */
 static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
   {
     THUMB16_INSN(0xb401),             /* push {r0} */
@@ -2063,6 +2061,17 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
   };
 
+/* V4T Thumb -> Thumb long branch stub. Using the stack is not
+   allowed.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
+  {
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop */
+    ARM_INSN(0xe59fc000),             /* ldr  ip, [pc, #0] */
+    ARM_INSN(0xe12fff1c),             /* bx   ip */
+    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
+  };
+
 /* V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
    available.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
@@ -2122,9 +2131,8 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_REL32, -4),     /* dcd  R_ARM_REL32(X) */
   };
 
-/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
-   support only this mode, or on V4T where it is expensive to switch
-   to ARM.  */
+/* Thumb -> Thumb long branch stub, PIC. Used on M-profile
+   architectures.  */
 static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
   {
     THUMB16_INSN(0xb401),             /* push {r0} */
@@ -2136,6 +2144,18 @@ static const insn_sequence elf32_arm_stu
     DATA_WORD(0, R_ARM_REL32, 4),     /* dcd  R_ARM_REL32(X) */
   };
 
+/* V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not
+   allowed.  */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
+  {
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop */
+    ARM_INSN(0xe59fc004),             /* ldr  ip, [pc, #4] */
+    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
+    ARM_INSN(0xe12fff1c),             /* bx   ip */
+    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
+  };
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -2146,6 +2166,7 @@ enum elf32_arm_stub_type
   arm_stub_long_branch_any_any,
   arm_stub_long_branch_v4t_arm_thumb,
   arm_stub_long_branch_thumb_only,
+  arm_stub_long_branch_v4t_thumb_thumb,
   arm_stub_long_branch_v4t_thumb_arm,
   arm_stub_short_branch_v4t_thumb_arm,
   arm_stub_long_branch_any_arm_pic,
@@ -2153,6 +2174,7 @@ enum elf32_arm_stub_type
   arm_stub_long_branch_v4t_arm_thumb_pic,
   arm_stub_long_branch_v4t_thumb_arm_pic,
   arm_stub_long_branch_thumb_only_pic,
+  arm_stub_long_branch_v4t_thumb_thumb_pic,
 };
 
 struct elf32_arm_stub_hash_entry
@@ -2923,14 +2945,14 @@ arm_type_of_stub (struct bfd_link_info *
        /* V5T and above.  */
        ? arm_stub_long_branch_any_thumb_pic
        /* On V4T, use Thumb code only.  */
-       : arm_stub_long_branch_thumb_only_pic)
+       : arm_stub_long_branch_v4t_thumb_thumb_pic)
 
     /* non-PIC stubs.  */
     : ((globals->use_blx)
        /* V5T and above.  */
        ? arm_stub_long_branch_any_any
        /* V4T.  */
-       : arm_stub_long_branch_thumb_only);
+       : arm_stub_long_branch_v4t_thumb_thumb);
  }
       else
  {
@@ -3336,6 +3358,10 @@ arm_size_one_stub (struct bfd_hash_entry
       template =  elf32_arm_stub_long_branch_thumb_only;
       template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only);
       break;
+    case arm_stub_long_branch_v4t_thumb_thumb:
+      template =  elf32_arm_stub_long_branch_v4t_thumb_thumb;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_thumb);
+      break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
       template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm);
@@ -3364,6 +3390,10 @@ arm_size_one_stub (struct bfd_hash_entry
       template = elf32_arm_stub_long_branch_thumb_only_pic;
       template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic);
       break;
+    case arm_stub_long_branch_v4t_thumb_thumb_pic:
+      template = elf32_arm_stub_long_branch_v4t_thumb_thumb_pic;
+      template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_thumb_pic);
+      break;
     default:
       BFD_FAIL ();
       return FALSE;
Index: ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d,v
retrieving revision 1.3
diff -u -p -r1.3 farcall-thumb-thumb-pic-veneer.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 26 Feb 2009 15:37:53 -0000 1.3
+++ ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d 12 Mar 2009 14:13:22 -0000
@@ -8,13 +8,13 @@ Disassembly of section .text:
  ...
 
 00001008 <__bar_veneer>:
-    1008: b401       push {r0}
-    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
-    100c: 46fc       mov ip, pc
-    100e: 4484       add ip, r0
-    1010: bc01       pop {r0}
-    1012: 4760       bx ip
-    1014: 02000005 .word 0x02000005
+    1008: 4778       bx pc
+    100a: 46c0       nop \(mov r8, r8\)
+    100c: e59fc004 ldr ip, \[pc, #4\] ; 1018 <__bar_veneer\+0x10>
+    1010: e08fc00c add ip, pc, ip
+    1014: e12fff1c bx ip
+    1018: 01fffffd .word 0x01fffffd
+    101c: 00000000 .word 0x00000000
 
 Disassembly of section .foo:
 
Index: ld/testsuite/ld-arm/farcall-thumb-thumb.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-thumb-thumb.d,v
retrieving revision 1.3
diff -u -p -r1.3 farcall-thumb-thumb.d
--- ld/testsuite/ld-arm/farcall-thumb-thumb.d 24 Feb 2009 22:43:10 -0000 1.3
+++ ld/testsuite/ld-arm/farcall-thumb-thumb.d 12 Mar 2009 14:13:22 -0000
@@ -8,12 +8,10 @@ Disassembly of section .text:
  \.\.\.
 
 00001008 <__bar_veneer>:
-    1008: b401       push {r0}
-    100a: 4802       ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\)
-    100c: 4684       mov ip, r0
-    100e: bc01       pop {r0}
-    1010: 4760       bx ip
-    1012: bf00       nop
+    1008: 4778       bx pc
+    100a: 46c0       nop \(mov r8, r8\)
+    100c: e59fc000 ldr ip, \[pc, #0\] ; 1014 <__bar_veneer\+0xc>
+    1010: e12fff1c bx ip
     1014: 02001015 .word 0x02001015
 Disassembly of section .foo:
 
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Nick Clifton
Hi Christophe,

> I propose a new patch that takes care of this issue.

Approved - please apply.

Cheers
   Nick


Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: pic take 2

Christophe Lyon
On 01.04.2009 17:51, Nick Clifton wrote:
> Hi Christophe,
>
>> I propose a new patch that takes care of this issue.
>
> Approved - please apply.
>

Thanks, committed.

Christophe.