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 stub sizing fix


This patch fixes a problem with stub sizing in the ARM backend.  I
started looking at this when I became curious about PR 10409, but I
now suspect that PR was fixed by Nathan's 2009-08-05 elf32-arm.c
patch.

The problem is due to the ARM backend creating stubs based only on the
destination symbol (also on input section stub group and reloc addend,
but within a single stub group you basically have only one stub per
destination);  We don't get multiple stubs if one branch to a
particular destination requires a different type of stub to that
required on another branch to the same destination.  However, the code
in arm_type_of_stub clearly returns stub types that depend on branch
offset and reloc type.  You could easily have both a
short_branch_v4t_thumb_arm and a long_branch_v4t_thumb_arm to the same
destination, with sorry results if the short version happened to be
created first.  Also, addition of stubs for one iteration of stub
sizing may cause a stub that was initially a
short_branch_v4t_thumb_arm to become a long_branch_v4t_thumb_arm on
the next iteration.  Fixed by updating existing stub_type for this
case.

I also add an assert that will trigger if there is a dependence on
reloc type.  I don't know enough about ARM code to know whether it's
possible to have, say, one branch to a function using R_ARM_THM_CALL
and another using R_ARM_THM_JUMP24 (possible tail call?).

OK to apply?

	* elf32-arm.c (arm_type_of_stub): Wrap overlong lines.
	(cortex_a8_erratum_scan): Fix uninitialised warning.
	(elf32_arm_size_stubs): Check and update stub_type in existing stubs.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.218
diff -u -p -r1.218 elf32-arm.c
--- bfd/elf32-arm.c	28 Dec 2009 18:55:16 -0000	1.218
+++ bfd/elf32-arm.c	14 Jan 2010 08:36:37 -0000
@@ -3075,7 +3075,9 @@ arm_type_of_stub (struct bfd_link_info *
   r_type = ELF32_R_TYPE (rel->r_info);
 
   /* Keep a simpler condition, for the sake of clarity.  */
-  if (globals->splt != NULL && hash != NULL && hash->root.plt.offset != (bfd_vma) -1)
+  if (globals->splt != NULL
+      && hash != NULL
+      && hash->root.plt.offset != (bfd_vma) -1)
     {
       use_plt = 1;
       /* Note when dealing with PLT entries: the main PLT stub is in
@@ -3181,7 +3183,9 @@ arm_type_of_stub (struct bfd_link_info *
 	    }
 	}
     }
-  else if (r_type == R_ARM_CALL || r_type == R_ARM_JUMP24 || r_type == R_ARM_PLT32)
+  else if (r_type == R_ARM_CALL
+	   || r_type == R_ARM_JUMP24
+	   || r_type == R_ARM_PLT32)
     {
       if (st_type == STT_ARM_TFUNC)
 	{
@@ -4022,7 +4026,7 @@ cortex_a8_erratum_scan (bfd *input_bfd,
 		  && last_was_32bit
 		  && ! last_was_branch)
                 {
-                  bfd_signed_vma offset;
+                  bfd_signed_vma offset = 0;
                   bfd_boolean force_target_arm = FALSE;
 		  bfd_boolean force_target_thumb = FALSE;
                   bfd_vma target;
@@ -4528,6 +4532,16 @@ elf32_arm_size_stubs (bfd *output_bfd,
 			  /* The proper stub has already been created.  */
 			  free (stub_name);
 			  stub_entry->target_value = sym_value;
+			  if (stub_entry->stub_type
+			      == arm_stub_short_branch_v4t_thumb_arm
+			      && (stub_type
+				  == arm_stub_long_branch_v4t_thumb_arm))
+			    {
+			      stub_entry->stub_type = stub_type;
+			      stub_changed = TRUE;
+			    }
+			  else
+			    BFD_ASSERT (stub_entry->stub_type == stub_type);
 			  break;
 			}
 

-- 
Alan Modra
Australia Development Lab, IBM


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