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]

Re: ARM/thumb interworking confuses unwinder


Hi,

Here is attached a patch that should fix Jonathan's issue: we now catch "short" call sequences, so the faulty stub shouldn't be generated in the code you are handling.

But it does not address the lack of unwind information for the stubs that use lr.

I don't know about the non-interworking-aware ones.  I suspect they're
just broken; we'd have to generate new unwind information for them.

I don't know how to do that; are there other examples in GNU ld that could serve me as a basis?



The comment at "Thumb->(non-interworking aware) ARM" is totally
mangled, I see... can't quite work out what it's saying.


I tried to reformat it in the attached patch.


Christophe.

2008-08-07  Christophe Lyon  <christophe.lyon@st.com>

	bfd/
	* elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define.
	(elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch.
	(arm_type_of_stub): Handle armv4t short branches. Update
	prototype.
	(arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch.
	(arm_build_one_stub): Likewise.
	(arm_size_one_stub): Likewise.
	(elf32_arm_size_stubs): Use new arm_type_of_stub prototype.
	(arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch.

	ld/testsuite/
	* ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
	* ld-arm/farcall-group2.s: Fix comment.
	* ld-arm/farcall-thumb-arm-short.d: New test.
	* ld-arm/farcall-thumb-arm-short.s: New test.

diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/bfd/elf32-arm.c binutils-cvs/src/bfd/elf32-arm.c
--- binutils-cvs-ref/src/bfd/elf32-arm.c	2008-07-28 08:46:31.000000000 +0200
+++ binutils-cvs/src/bfd/elf32-arm.c	2008-08-07 14:45:32.000000000 +0200
@@ -2044,6 +2044,13 @@
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
   };
 
+static const bfd_vma arm_thumb_arm_v4t_short_branch_stub[] =
+  {
+    0x46c04778,         /* bx   pc */
+                        /* nop   */
+    0xea000000,         /* b    (X) */
+  };
+
 static const bfd_vma arm_pic_long_branch_stub[] =
   {
     0xe59fc000,         /* ldr   r12, [pc] */
@@ -2062,6 +2069,7 @@
   arm_thumb_v4t_stub_long_branch,
   arm_thumb_thumb_stub_long_branch,
   arm_thumb_arm_v4t_stub_long_branch,
+  arm_thumb_arm_v4t_stub_short_branch,
   arm_stub_pic_long_branch,
 };
 
@@ -2737,6 +2745,7 @@
     {
     case arm_thumb_thumb_stub_long_branch:
     case arm_thumb_arm_v4t_stub_long_branch:
+    case arm_thumb_arm_v4t_stub_short_branch:
       return TRUE;
     case arm_stub_none:
       BFD_FAIL ();
@@ -2755,7 +2764,10 @@
 		  const Elf_Internal_Rela *rel,
 		  unsigned char st_type,
 		  struct elf32_arm_link_hash_entry *hash,
-		  bfd_vma destination)
+		  bfd_vma destination,
+		  asection* sym_sec,
+		  bfd* input_bfd,
+		  const char* name)
 {
   bfd_vma location;
   bfd_signed_vma branch_offset;
@@ -2825,6 +2837,16 @@
 	  else
 	    {
 	      /* Thumb to arm.  */
+	      if (sym_sec != NULL
+		  && sym_sec->owner != NULL
+		  && !INTERWORK_FLAG (sym_sec->owner))
+		{
+		  (*_bfd_error_handler)
+		    (_("%B(%s): warning: interworking not enabled.\n"
+		       "  first occurrence: %B: thumb call to arm"),
+		     sym_sec->owner, input_bfd, name);
+		}
+
 	      stub_type = (info->shared | globals->pic_veneer)
 		? ((globals->use_blx)
 		   ? arm_stub_pic_long_branch
@@ -2832,6 +2854,13 @@
 		: (globals->use_blx)
 		? arm_stub_long_branch
 		: arm_thumb_arm_v4t_stub_long_branch;
+
+	      /* Handle v4t short branches */
+	      if ( (stub_type == arm_thumb_arm_v4t_stub_long_branch)
+		   && (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET)
+		   && (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET)) {
+		stub_type = arm_thumb_arm_v4t_stub_short_branch;
+	      }
 	    }
 	}
     }
@@ -2840,6 +2869,17 @@
       if (st_type == STT_ARM_TFUNC)
 	{
 	  /* Arm to thumb.  */
+
+	  if (sym_sec != NULL
+	      && sym_sec->owner != NULL
+	      && !INTERWORK_FLAG (sym_sec->owner))
+	    {
+	      (*_bfd_error_handler)
+		(_("%B(%s): warning: interworking not enabled.\n"
+		   "  first occurrence: %B: thumb call to arm"),
+		 sym_sec->owner, input_bfd, name);
+	    }
+
 	  /* We have an extra 2-bytes reach because of the mode change
 	     (bit 24 (H) of BLX encoding).  */
 	  if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
@@ -3097,6 +3137,10 @@
       template =  arm_thumb_arm_v4t_long_branch_stub;
       template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      template =  arm_thumb_arm_v4t_short_branch_stub;
+      template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+      break;
     case arm_stub_pic_long_branch:
       template = arm_pic_long_branch_stub;
       template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3146,6 +3190,19 @@
 				stub_bfd, stub_sec, stub_sec->contents,
 				stub_entry->stub_offset + 16, sym_value, 0);
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      {
+	long int rel_offset;
+	static const insn32 t2a3_b_insn = 0xea000000;
+
+	rel_offset = sym_value - (stub_addr + 8 + 4);
+
+	put_arm_insn (globals, stub_bfd,
+		      (bfd_vma) t2a3_b_insn | ((rel_offset >> 2) & 0x00FFFFFF),
+		      loc + 4);
+      }
+      break;
+
     case arm_stub_pic_long_branch:
       /* We want the value relative to the address 8 bytes from the
 	 start of the stub.  */
@@ -3196,6 +3253,10 @@
       template =  arm_thumb_arm_v4t_long_branch_stub;
       template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      template =  arm_thumb_arm_v4t_short_branch_stub;
+      template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+      break;
     case arm_stub_pic_long_branch:
       template = arm_pic_long_branch_stub;
       template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3602,7 +3663,8 @@
 
 		  /* Determine what (if any) linker stub is needed.  */
 		  stub_type = arm_type_of_stub (info, section, irela, st_type,
-						hash, destination);
+						hash, destination, sym_sec,
+						input_bfd, sym_name);
 		  if (stub_type == arm_stub_none)
 		    continue;
 
@@ -3847,17 +3909,17 @@
 
    .thumb                               .thumb
    .align 2                             .align 2
-   __func_from_thumb:              __func_from_thumb:
+__func_from_thumb:                 __func_from_thumb:
    bx pc                                push {r6, lr}
    nop                                  ldr  r6, __func_addr
-   .arm                                         mov  lr, pc
-   __func_change_to_arm:                        bx   r6
-   b func                       .arm
-   __func_back_to_thumb:
-   ldmia r13! {r6, lr}
-   bx    lr
-   __func_addr:
-   .word        func  */
+   .arm                                 mov  lr, pc
+__func_change_to_arm:                   bx   r6
+   b func                               .arm
+                                   __func_back_to_thumb:
+                                        ldmia r13! {r6, lr}
+                                        bx    lr
+                                   __func_addr:
+                                        .word        func  */
 
 #define THUMB2ARM_GLUE_SIZE 8
 static const insn16 t2a1_bx_pc_insn = 0x4778;
@@ -11276,6 +11338,12 @@
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
 	return FALSE;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
+	return FALSE;
+      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
+	return FALSE;
+      break;
     case arm_stub_pic_long_branch:
       if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
 	return FALSE;
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/arm-elf.exp binutils-cvs/src/ld/testsuite/ld-arm/arm-elf.exp
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/arm-elf.exp	2008-07-18 22:49:12.000000000 +0200
+++ binutils-cvs/src/ld/testsuite/ld-arm/arm-elf.exp	2008-08-07 14:46:24.000000000 +0200
@@ -207,7 +207,7 @@
      {"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" {thumb2-bl.s}
       {{objdump -dr thumb2-bl.d}}
       "thumb2-bl"}
-    
+
     {"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s}
      {{objdump -d armv4-bx.d}}
      "armv4-bx"}
@@ -260,6 +260,9 @@
     {"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 (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"}
     {"Thumb-ARM farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-blx.d}}
      "farcall-thumb-arm-blx"}
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-group2.s binutils-cvs/src/ld/testsuite/ld-arm/farcall-group2.s
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-group2.s	2008-05-23 16:16:16.000000000 +0200
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-group2.s	2008-08-07 10:48:15.000000000 +0200
@@ -1,10 +1,7 @@
-
 @ Test to ensure that ARM calls exceeding 32Mb generate stubs.
 
-@ We will place the section .foo at 0x2000.
-
 	.text
-myfunc:	
+myfunc:
 	bl bar3
 	bl bar4
 	bl bar5
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d	1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.d	2008-08-06 13:48:05.000000000 +0200
@@ -0,0 +1,14 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000:	4778      	bx	pc
+    1002:	46c0      	nop			\(mov r8, r8\)
+    1004:	ea000402 	b	2014 <bar>
+00001008 <_start>:
+    1008:	f7ff fffa 	bl	1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+00002014 <bar>:
+    2014:	e12fff1e 	bx	lr
diff --exclude=CVS --exclude='*~' -Naur binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s
--- binutils-cvs-ref/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s	1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs/src/ld/testsuite/ld-arm/farcall-thumb-arm-short.s	2008-08-06 13:38:48.000000000 +0200
@@ -0,0 +1,21 @@
+@ Test to ensure that a Thumb to ARM call within 4Mb does not generate a stub.
+
+	.global _start
+	.syntax unified
+
+@ We will place the section .text at 0x1000.
+
+	.text
+	.thumb_func
+_start:
+	bl bar
+
+@ We will place the section .foo at 0x2014.
+
+	.section .foo, "xa"
+
+	.arm
+	.type bar, %function
+bar:
+	bx lr
+

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