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: be8


Hi all,

Following our recent discussion, I propose the attached patch to fix big-endian / be8 stubs encoding issues.

I am not particularly proud of the way it's now done, but it does the job.
In short, the Thumb instructions in the stubs now use 1 entry per instruction (instead of 2 instr per entry), but this implies that the encoding functions know the exact layout of each stub, so it makes maintenance a bit more painful (I added some comments to warn about that).


I have added one more test (farcall-thumb-arm-be8).

Once this is OK, I'll come back to my original patches to improve PIC/PLT support.

Christophe.
2009-02-20  Christophe Lyon  <christophe.lyon@st.com>

	bfd/
	* elf32-arm.c (elf32_arm_stub_long_branch_thumb_only): Split Thumb
	instructions encoding.
	(elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise.
	(elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise.
	(arm_build_one_stub): Encode Arm and Thumb instructions separately
	to take endianness into account.
	(arm_size_one_stub): Hardcode size of stubs.

	testsuite/
	* ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test.
	* ld-arm/farcall-thumb-arm-be8.d: New expected result.
	* ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.172
diff -u -p -r1.172 elf32-arm.c
--- bfd/elf32-arm.c	18 Feb 2009 16:56:37 -0000	1.172
+++ bfd/elf32-arm.c	23 Feb 2009 09:50:07 -0000
@@ -2010,6 +2010,9 @@ static const bfd_vma elf32_arm_symbian_p
 #define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
 #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
 
+/* CAUTION: when updating the stubs code, don't forget to also update
+   arm_build_one_stub and arm_size_one_stub below.  */
+
 /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
    to reach the stub if necessary.  */
 static const bfd_vma elf32_arm_stub_long_branch_any_any[] =
@@ -2032,12 +2035,12 @@ static const bfd_vma elf32_arm_stub_long
    to ARM.  */
 static const bfd_vma elf32_arm_stub_long_branch_thumb_only[] =
   {
-    0x4e02b540,         /* push {r6, lr} */
-                        /* ldr  r6, [pc, #8] */
-    0x473046fe,         /* mov  lr, pc */
-                        /* bx   r6 */
-    0xbf00bd40,         /* pop  {r6, pc} */
-                        /* nop */
+    0xb540,             /* push {r6, lr} */
+    0x4e02,             /* ldr  r6, [pc, #8] */
+    0x46fe,             /* mov  lr, pc */
+    0x4730,             /* bx   r6 */
+    0xbd40,             /* pop  {r6, pc} */
+    0xbf00,             /* nop */
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
   };
 
@@ -2045,10 +2048,10 @@ static const bfd_vma elf32_arm_stub_long
    available.  */
 static const bfd_vma elf32_arm_stub_long_branch_v4t_thumb_arm[] =
   {
-    0x4e03b540,         /* push {r6, lr} */
-                        /* ldr  r6, [pc, #12] */
-    0x473046fe,         /* mov  lr, pc */
-                        /* bx   r6 */
+    0xb540,             /* push {r6, lr} */
+    0x4e03,             /* ldr  r6, [pc, #12] */
+    0x46fe,             /* mov  lr, pc */
+    0x4730,             /* bx   r6 */
     0xe8bd4040,         /* pop  {r6, pc} */
     0xe12fff1e,         /* bx   lr */
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
@@ -2058,8 +2061,8 @@ static const bfd_vma elf32_arm_stub_long
    one, when the destination is close enough.  */
 static const bfd_vma elf32_arm_stub_short_branch_v4t_thumb_arm[] =
   {
-    0x46c04778,         /* bx   pc */
-                        /* nop   */
+    0x4778,             /* bx   pc */
+    0x46c0,             /* nop   */
     0xea000000,         /* b    (X) */
   };
 
@@ -3089,8 +3092,7 @@ arm_build_one_stub (struct bfd_hash_entr
   bfd_vma stub_addr;
   bfd_byte *loc;
   bfd_vma sym_value;
-  int template_size;
-  int size;
+  int size = 0;
   const bfd_vma *template;
   int i;
   struct elf32_arm_link_hash_table * globals;
@@ -3119,49 +3121,85 @@ arm_build_one_stub (struct bfd_hash_entr
 	       + stub_entry->target_section->output_offset
 	       + stub_entry->target_section->output_section->vma);
 
+  /* CAUTION: the calls to put_arm_insn, put_thumb_insn and bfd_put_32
+     below must be kept in sync with the actual stubs contents.  */
   switch (stub_entry->stub_type)
     {
     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 (bfd_vma)) * 4;
+      for (i = 0; i < 1; i++)
+	{
+	  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 4;
+	}
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       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 (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+	{
+	  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 4;
+	}
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       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 (bfd_vma)) * 4;
+      for (i = 0; i < 6; i++)
+	{
+	  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 2;
+	}
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       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 (bfd_vma)) * 4;
+      for (i = 0; i < 4; i++)
+	{
+	  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 2;
+	}
+      for (i = 4; i < 6; i++)
+	{
+	  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 4;
+	}
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       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 (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+	{
+	  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 2;
+	}
+      size += 4;
       break;
+
     case arm_stub_long_branch_any_any_pic:
       template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+	{
+	  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+	  size += 4;
+	}
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     default:
       BFD_FAIL ();
       return FALSE;
     }
 
-  size = 0;
-  for (i = 0; i < (template_size / 4); i++)
-    {
-      /* A 0 pattern is a placeholder, every other pattern is an
-	 instruction.  */
-      if (template[i] != 0)
-	put_arm_insn (globals, stub_bfd, template[i], loc + size);
-      else
-	bfd_put_32 (stub_bfd, template[i], loc + size);
-
-      size += 4;
-    }
   stub_sec->size += size;
 
   /* Destination is Thumb. Force bit 0 to 1 to reflect this.  */
@@ -3229,38 +3267,38 @@ arm_size_one_stub (struct bfd_hash_entry
   struct elf32_arm_link_hash_table *htab;
   const bfd_vma *template;
   int template_size;
-  int size;
-  int i;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   htab = (struct elf32_arm_link_hash_table *) in_arg;
 
+  /* CAUTION: the stub sizes below must be kept in sync with the
+     actual stubs contents.  */
   switch (stub_entry->stub_type)
     {
     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 (bfd_vma)) * 4;
+      template_size = 8;
       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 (bfd_vma)) * 4;
+      template_size = 12;
       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 (bfd_vma)) * 4;
+      template_size = 16;
       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 (bfd_vma)) * 4;
+      template_size = 20;
       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 (bfd_vma)) * 4;
+      template_size = 8;
       break;
     case arm_stub_long_branch_any_any_pic:
       template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+      template_size = 12;
       break;
     default:
       BFD_FAIL ();
@@ -3268,11 +3306,8 @@ arm_size_one_stub (struct bfd_hash_entry
       break;
     }
 
-  size = 0;
-  for (i = 0; i < (template_size / 4); i++)
-      size += 4;
-  size = (size + 7) & ~7;
-  stub_entry->stub_sec->size += size;
+  template_size = (template_size + 7) & ~7;
+  stub_entry->stub_sec->size += template_size;
   return TRUE;
 }
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.44
diff -u -p -r1.44 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	5 Feb 2009 21:54:43 -0000	1.44
+++ ld/testsuite/ld-arm/arm-elf.exp	23 Feb 2009 09:50:13 -0000
@@ -284,6 +284,9 @@ set armeabitests {
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm"}
+    {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-be8.d}}
+     "farcall-thumb-arm"}
     {"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
      {{objdump -d farcall-thumb-arm-short.d}}
      "farcall-thumb-arm-short"}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-arm-arm-be8.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-arm-arm-be8.d
--- ld/testsuite/ld-arm/farcall-arm-arm-be8.d	25 Jun 2008 14:28:48 -0000	1.2
+++ ld/testsuite/ld-arm/farcall-arm-arm-be8.d	23 Feb 2009 09:50:13 -0000
@@ -3,12 +3,12 @@
 Disassembly of section .text:
 
 00001000 <__bar_veneer>:
-    1000:	04f01fe5 	.*
+    1000:	04f01fe5 	ldr	pc, \[pc, #-4\]	; 1004 <__bar_veneer\+0x4>
     1004:	02001020 	.word	0x02001020
 
 00001008 <_start>:
-    1008:	fcffffeb 	.*
+    1008:	fcffffeb 	bl	1000 <__bar_veneer>
 Disassembly of section .foo:
 
 02001020 <bar>:
- 2001020:	1eff2fe1 	.*
+ 2001020:	1eff2fe1 	bx	lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-thumb-arm-be8.d	23 Feb 2009 09:50:13 -0000
@@ -0,0 +1,20 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000:	40b5      	push	{r6, lr}
+    1002:	034e      	ldr	r6, \[pc, #12\]	\(1010 <__bar_from_thumb\+0x10>\)
+    1004:	fe46      	mov	lr, pc
+    1006:	3047      	bx	r6
+    1008:	4040bde8 	pop	{r6, lr}
+    100c:	1eff2fe1 	bx	lr
+    1010:	02001014 	.word	0x02001014
+    1014:	00000000 	.word	0x00000000
+
+00001018 <_start>:
+    1018:	fff7 f2ff 	bl	1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014:	1eff2fe1 	bx	lr

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