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]

ARM long branch stubs: pic take 2


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  <christophe.lyon@st.com>

	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

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