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 uClinux branch veneers


uClinux executabes are created by linking a static binary (using absolute 
addressing) with --emit-relocs, and using the relocations to tell the OS 
loader how to relocate the boundary. The compiler generated branch veneers 
don't have any relocations, so elf2flt/uclinux doesn't know to relocate them.

The patch below adds a new ld option to generation of PIC sequences for 
ARM->Thumb interworking veneers.  Normally this only happens when generating 
a shared library or PIE.

Other possible solutions to this problem are to hack elf2flt to magically 
recognise veneers and fix them up (ugly and fragile), or to output 
relocations for the veneers (hard).

I considered creating a uclinux specific linker emulation. However the 
commandline option is conceivably useful in other circumstances, so I didn't 
bother.

Tested on arm-none-eabi and arm-uclinux-uclibceabi.
Applied to head.

Paul

2007-03-20  Paul Brook  <paul@codesourcery.com>

	ld/
	* emultempl/armelf.em (pic_veneer): New variable.
	(PARSE_AND_LIST_PROLOGUE): Add OPTION_PIC_VENEER.
	(PARSE_AND_LIST_ARGS_CASES): Ditto.
	(PARSE_AND_LIST_LONGOPTS): Add "pic-veneer".
	(PARSE_AND_LIST_OPTIONS): Ditto.
	* ld.texinfo: Document --pic-veneer.

	ld/testsuite/
	* ld-arm/arm-elf.exp (ld-arm/arm-elf.exp): Add arm-pic-veneer.
	* ld-arm/arm-pic-veneer.d: New test.
	* ld-arm/arm-pic-veneer.s: New test.

	bfd/
	* bfd-in.h (bfd_elf32_arm_set_target_relocs): Update prototype.
	* bfd-in2.h: Regenerate.
	* elf32-arm.c (elf32_arm_link_hash_table): Add pic_veneer.
	(record_arm_to_thumb_glue): Use globals->pic_veneer.
	(elf32_arm_create_thumb_stub): Ditto.
	(bfd_elf32_arm_set_target_relocs): Set globals->pic_veneer.
Index: bfd/bfd-in.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/bfd-in.h,v
retrieving revision 1.125
diff -u -p -r1.125 bfd-in.h
--- bfd/bfd-in.h	20 Mar 2007 14:24:53 -0000	1.125
+++ bfd/bfd-in.h	20 Mar 2007 18:55:53 -0000
@@ -903,7 +903,7 @@ extern bfd_boolean bfd_elf32_arm_process
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   int);
+   int, int);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
Index: bfd/bfd-in2.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/bfd-in2.h,v
retrieving revision 1.416
diff -u -p -r1.416 bfd-in2.h
--- bfd/bfd-in2.h	20 Mar 2007 14:24:53 -0000	1.416
+++ bfd/bfd-in2.h	20 Mar 2007 18:58:03 -0000
@@ -910,7 +910,7 @@ extern bfd_boolean bfd_elf32_arm_process
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   int);
+   int, int);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.107
diff -u -p -r1.107 elf32-arm.c
--- bfd/elf32-arm.c	20 Mar 2007 14:24:53 -0000	1.107
+++ bfd/elf32-arm.c	20 Mar 2007 18:24:37 -0000
@@ -2191,6 +2191,9 @@ struct elf32_arm_link_hash_table
     /* Global counter for the number of fixes we have emitted.  */
     int num_vfp11_fixes;
 
+    /* Nonzero to force PIC branch veneers.  */
+    int pic_veneer;
+
     /* The number of bytes in the initial entry in the PLT.  */
     bfd_size_type plt_header_size;
 
@@ -2714,7 +2717,8 @@ record_arm_to_thumb_glue (struct bfd_lin
 
   free (tmp_name);
 
-  if ((link_info->shared || globals->root.is_relocatable_executable))
+  if (link_info->shared || globals->root.is_relocatable_executable
+      || globals->pic_veneer)
     size = ARM2THUMB_PIC_GLUE_SIZE;
   else
     size = ARM2THUMB_STATIC_GLUE_SIZE;
@@ -3868,7 +3872,7 @@ bfd_elf32_arm_set_target_relocs (struct 
                                  int fix_v4bx,
 				 int use_blx,
                                  bfd_arm_vfp11_fix vfp11_fix,
-				 int no_enum_warn)
+				 int no_enum_warn, int pic_veneer)
 {
   struct elf32_arm_link_hash_table *globals;
 
@@ -3889,6 +3893,7 @@ bfd_elf32_arm_set_target_relocs (struct 
   globals->fix_v4bx = fix_v4bx;
   globals->use_blx |= use_blx;
   globals->vfp11_fix = vfp11_fix;
+  globals->pic_veneer = pic_veneer;
 
   elf32_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
 }
@@ -4127,7 +4132,8 @@ elf32_arm_create_thumb_stub (struct bfd_
       --my_offset;
       myh->root.u.def.value = my_offset;
 
-      if ((info->shared || globals->root.is_relocatable_executable))
+      if (info->shared || globals->root.is_relocatable_executable
+	  || globals->pic_veneer)
 	{
 	  /* For relocatable objects we can't use absolute addresses,
 	     so construct the address from a relative offset.  */
Index: ld/ld.texinfo
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/ld.texinfo,v
retrieving revision 1.187
diff -u -p -r1.187 ld.texinfo
--- ld/ld.texinfo	20 Mar 2007 14:24:56 -0000	1.187
+++ ld/ld.texinfo	20 Mar 2007 18:23:51 -0000
@@ -5406,6 +5406,13 @@ trampoline address instead of the functi
 case when a pointer to a function is taken. The pointer will in fact
 point to the function trampoline.
 
+@cindex PIC_VENEER
+@kindex --pic-veneer
+The @samp{--pic-veneer} switch makes the linker use PIC sequences for
+ARM/Thumb interworking veneers, even if the rest of the binary
+is not PIC.  This avoids problems on uClinux targets where
+@samp{--emit-relocs} is used to generate relocatable binaries.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/emultempl/armelf.em,v
retrieving revision 1.54
diff -u -p -r1.54 armelf.em
--- ld/emultempl/armelf.em	20 Mar 2007 14:24:57 -0000	1.54
+++ ld/emultempl/armelf.em	20 Mar 2007 18:53:59 -0000
@@ -37,6 +37,7 @@ static int fix_v4bx = 0;
 static int use_blx = 0;
 static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT;
 static int no_enum_size_warning = 0;
+static int pic_veneer = 0;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -241,7 +242,8 @@ arm_elf_create_output_section_statements
 {
   bfd_elf32_arm_set_target_relocs (output_bfd, &link_info, target1_is_rel,
 				   target2_type, fix_v4bx, use_blx,
-				   vfp11_denorm_fix, no_enum_size_warning);
+				   vfp11_denorm_fix, no_enum_size_warning,
+				   pic_veneer);
 }
 
 EOF
@@ -259,6 +261,7 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_USE_BLX			307
 #define OPTION_VFP11_DENORM_FIX		308
 #define OPTION_NO_ENUM_SIZE_WARNING	309
+#define OPTION_PIC_VENEER		310
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -274,6 +277,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "use-blx", no_argument, NULL, OPTION_USE_BLX},
   { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX},
   { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
+  { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -286,6 +290,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("     --use-blx                Enable use of BLX instructions\n"));
   fprintf (file, _("     --vfp11-denorm-fix       Specify how to fix VFP11 denorm erratum\n"));
   fprintf (file, _("     --no-enum-size-warning   Don'\''t warn about objects with incompatible enum sizes\n"));
+  fprintf (file, _("     --pic-veneer             Always generate PIC interworking veneers\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -335,6 +340,10 @@ PARSE_AND_LIST_ARGS_CASES='
     case OPTION_NO_ENUM_SIZE_WARNING:
       no_enum_size_warning = 1;
       break;
+
+    case OPTION_PIC_VENEER:
+      pic_veneer = 1;
+      break;
 '
 
 # We have our own after_open and before_allocation functions, but they call
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.21
diff -u -p -r1.21 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	28 Feb 2007 17:14:39 -0000	1.21
+++ ld/testsuite/ld-arm/arm-elf.exp	20 Mar 2007 18:23:18 -0000
@@ -156,6 +156,9 @@ set armelftests {
     {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s}
      {{objdump -sj.data gc-unwind.d}}
      "gc-unwind"}
+    {"arm-pic-veneer" "-static -T arm.ld --pic-veneer" "" {arm-pic-veneer.s}
+     {{objdump -d arm-pic-veneer.d}}
+     "arm-pic-veneer"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/arm-pic-veneer.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-pic-veneer.d
diff -N ld/testsuite/ld-arm/arm-pic-veneer.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-pic-veneer.d	20 Mar 2007 00:38:29 -0000
@@ -0,0 +1,17 @@
+
+.*:     file format.*
+
+Disassembly of section .text:
+
+00008000 <_start>:
+    8000:	ea000000 	b	8008 <__foo_from_arm>
+
+00008004 <foo>:
+    8004:	46c0      	nop			\(mov r8, r8\)
+    8006:	4770      	bx	lr
+
+00008008 <__foo_from_arm>:
+    8008:	e59fc004 	ldr	ip, \[pc, #4\]	; 8014 <__foo_from_arm\+0xc>
+    800c:	e08cc00f 	add	ip, ip, pc
+    8010:	e12fff1c 	bx	ip
+    8014:	fffffff1 	undefined instruction 0xfffffff1
Index: ld/testsuite/ld-arm/arm-pic-veneer.s
===================================================================
RCS file: ld/testsuite/ld-arm/arm-pic-veneer.s
diff -N ld/testsuite/ld-arm/arm-pic-veneer.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-pic-veneer.s	20 Mar 2007 00:38:29 -0000
@@ -0,0 +1,14 @@
+.text
+.arm
+.global _start
+.type _start, %function
+_start:
+b foo
+
+.thumb
+.global foo
+.type foo, %function
+foo:
+nop
+bx lr
+

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