This is the mail archive of the binutils@sources.redhat.com 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: [PATCH] Enable use of ARMv5t BLX for Thumb-mode calls via PLT


Daniel Jacobowitz wrote:
On Mon, Apr 11, 2005 at 07:55:12PM +0100, Julian Brown wrote:

With this patch, the option "--use-thumb-blx" can be passed to the linker to enable the use of the BLX instruction when the target supports it. The format of the PLT itself isn't changed by this patch: there is still a Thumb stub before each ARM PLT entry, but it is now unused. The ARM mode entry is called directly instead.


The Thumb stub is never referenced from outside of the object.  So, if
we aren't going to branch to it, no point in emitting it either.  Patch
looks plausible to me...

This is a new version of the patch which doesn't emit Thumb stubs before PLT entries if BLX is being used to call them, and also renames the switch to --use-blx as per Paul's suggestion.


Re-tested on arm-none-eabi and arm-none-symbianelf.

OK to apply?

ChangeLog:

bfd:
  * bfd-in.h (bfd_elf32_arm_set_target_relocs): Update prototype.
  * bfd-in2.h: Regenerate.
  * elf32-arm.c (elf32_arm_link_hash_table): New field, 'use_blx'.
  (elf32_arm_link_hash_table_create): Initialise fix_v4bx, use_blx.
  (bfd_elf32_arm_set_target_relocs): Handle use_blx.
  (elf32_arm_final_link_relocate): Use Thumb BLX for R_ARM_THM_PC22
  relocations if requested to.
  (allocate_dynrelocs): Don't count size of omitted Thumb stubs based on
  use_blx rather than symbian_p.
  (elf32_arm_finish_dynamic_symbol): Don't output Thumb PLT stubs if
  use_blx is in effect.
  (elf32_arm_symbian_link_hash_table_create): Enable use_blx by default
  for SymbianOS.

ld:
  * ld.texinfo: Document --use-blx.
  * emultempl/armelf.em (use_blx): New variable.
  (arm_elf_create_output_section_statements): Communicate value of
  use_blx to bfd.
  (PARSE_AND_LIST_PROLOGUE): Add OPTION_USE_BLX.
  (PARSE_AND_LIST_OPTIONS): Add --use-blx option.
  (PARSE_AND_LIST_ARGS_CASES): Add OPTION_USE_BLX case.
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.97
diff -c -p -r1.97 bfd-in.h
*** bfd/bfd-in.h	30 Mar 2005 17:19:27 -0000	1.97
--- bfd/bfd-in.h	12 Apr 2005 20:57:45 -0000
*************** extern bfd_boolean bfd_elf32_arm_process
*** 816,822 ****
    (bfd *, struct bfd_link_info *, int);
  
  void bfd_elf32_arm_set_target_relocs
!   (struct bfd_link_info *, int, char *, int);
  
  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
    (bfd *, struct bfd_link_info *);
--- 816,822 ----
    (bfd *, struct bfd_link_info *, int);
  
  void bfd_elf32_arm_set_target_relocs
!   (struct bfd_link_info *, int, char *, int, int);
  
  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
    (bfd *, struct bfd_link_info *);
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.31
diff -c -p -r1.31 elf32-arm.c
*** bfd/elf32-arm.c	8 Apr 2005 11:47:59 -0000	1.31
--- bfd/elf32-arm.c	12 Apr 2005 20:57:45 -0000
*************** struct elf32_arm_link_hash_table
*** 1324,1329 ****
--- 1324,1332 ----
      /* Nonzero to fix BX instructions for ARMv4 targets.  */
      int fix_v4bx;
  
+     /* Nonzero if the ARM/Thumb BLX instructions are available for use.  */
+     int use_blx;
+ 
      /* The number of bytes in the initial entry in the PLT.  */
      bfd_size_type plt_header_size;
  
*************** elf32_arm_link_hash_table_create (bfd *a
*** 1559,1564 ****
--- 1562,1569 ----
    ret->plt_header_size = 20;
    ret->plt_entry_size = 12;
  #endif
+   ret->fix_v4bx = 0;
+   ret->use_blx = 0;
    ret->symbian_p = 0;
    ret->use_rel = 1;
    ret->sym_sec.abfd = NULL;
*************** void
*** 2125,2131 ****
  bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
  				 int target1_is_rel,
  				 char * target2_type,
!                                  int fix_v4bx)
  {
    struct elf32_arm_link_hash_table *globals;
  
--- 2130,2137 ----
  bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
  				 int target1_is_rel,
  				 char * target2_type,
!                                  int fix_v4bx,
! 				 int use_blx)
  {
    struct elf32_arm_link_hash_table *globals;
  
*************** bfd_elf32_arm_set_target_relocs (struct 
*** 2144,2149 ****
--- 2150,2156 ----
  			  target2_type);
      }
    globals->fix_v4bx = fix_v4bx;
+   globals->use_blx |= use_blx;
  }
  #endif
  
*************** elf32_arm_final_link_relocate (reloc_how
*** 2893,2898 ****
--- 2900,2906 ----
  	bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
  	bfd_vma check;
  	bfd_signed_vma signed_check;
+ 	bfd_boolean thumb_plt_call = FALSE;
  
  	/* Need to refetch the addend and squish the two 11 bit pieces
  	   together.  */
*************** elf32_arm_final_link_relocate (reloc_how
*** 2942,2949 ****
  	    value = (splt->output_section->vma
  		     + splt->output_offset
  		     + h->plt.offset);
! 	    /* Target the Thumb stub before the ARM PLT entry.  */
! 	    value -= 4;
  	    *unresolved_reloc_p = FALSE;
  	  }
  
--- 2950,2968 ----
  	    value = (splt->output_section->vma
  		     + splt->output_offset
  		     + h->plt.offset);
!  	    if (globals->use_blx)
!  	      {
!  		/* If the Thumb BLX instruction is available, convert the
! 		   BL to a BLX instruction to call the ARM-mode PLT entry.  */
!  		if ((lower_insn & (0x3 << 11)) == 0x3 << 11)
! 		  {
! 		    lower_insn = (lower_insn & ~(0x3 << 11)) | 0x1 << 11;
! 		    thumb_plt_call = TRUE;
! 		  }
!  	      }
!  	    else
!  	      /* Target the Thumb stub before the ARM PLT entry.  */
!  	      value -= PLT_THUMB_STUB_SIZE;
  	    *unresolved_reloc_p = FALSE;
  	  }
  
*************** elf32_arm_final_link_relocate (reloc_how
*** 2967,2974 ****
  	  overflow = TRUE;
  
  #ifndef OLD_ARM_ABI
! 	if (r_type == R_ARM_THM_XPC22
! 	    && ((lower_insn & 0x1800) == 0x0800))
  	  /* For a BLX instruction, make sure that the relocation is rounded up
  	     to a word boundary.  This follows the semantics of the instruction
  	     which specifies that bit 1 of the target address will come from bit
--- 2986,2994 ----
  	  overflow = TRUE;
  
  #ifndef OLD_ARM_ABI
! 	if ((r_type == R_ARM_THM_XPC22
! 	     && ((lower_insn & 0x1800) == 0x0800))
! 	    || thumb_plt_call)
  	  /* For a BLX instruction, make sure that the relocation is rounded up
  	     to a word boundary.  This follows the semantics of the instruction
  	     which specifies that bit 1 of the target address will come from bit
*************** allocate_dynrelocs (struct elf_link_hash
*** 5059,5065 ****
  
  	  /* If we will insert a Thumb trampoline before this PLT, leave room
  	     for it.  */
! 	  if (!htab->symbian_p && eh->plt_thumb_refcount > 0)
  	    {
  	      h->plt.offset += PLT_THUMB_STUB_SIZE;
  	      s->size += PLT_THUMB_STUB_SIZE;
--- 5079,5085 ----
  
  	  /* If we will insert a Thumb trampoline before this PLT, leave room
  	     for it.  */
! 	  if (!htab->use_blx && eh->plt_thumb_refcount > 0)
  	    {
  	      h->plt.offset += PLT_THUMB_STUB_SIZE;
  	      s->size += PLT_THUMB_STUB_SIZE;
*************** elf32_arm_finish_dynamic_symbol (bfd * o
*** 5632,5638 ****
  
  	  BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
  
! 	  if (eh->plt_thumb_refcount > 0)
  	    {
  	      bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
  			  splt->contents + h->plt.offset - 4);
--- 5652,5658 ----
  
  	  BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
  
! 	  if (!htab->use_blx && eh->plt_thumb_refcount > 0)
  	    {
  	      bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
  			  splt->contents + h->plt.offset - 4);
*************** elf32_arm_symbian_link_hash_table_create
*** 6505,6510 ****
--- 6525,6532 ----
        /* The PLT entries are each three instructions.  */
        htab->plt_entry_size = 4 * NUM_ELEM (elf32_arm_symbian_plt_entry);
        htab->symbian_p = 1;
+       /* Symbian uses armv5t or above, so use_blx is always true.  */
+       htab->use_blx = 1;
        htab->root.is_relocatable_executable = 1;
      }
    return ret;
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.140
diff -c -p -r1.140 ld.texinfo
*** ld/ld.texinfo	1 Feb 2005 17:31:01 -0000	1.140
--- ld/ld.texinfo	12 Apr 2005 20:57:45 -0000
*************** linker, which causes v4t @code{BX rM} in
*** 5262,5267 ****
--- 5262,5278 ----
  In the former case, the switch should not be used, and @samp{R_ARM_V4BX}
  relocations are ignored.
  
+ @cindex USE_BLX
+ @kindex --use-blx
+ The @samp{--use-blx} switch enables the linker to use ARM/Thumb
+ BLX instructions (available on ARMv5t and above) in various
+ situations. Currently it is used to perform calls via the PLT from
+ Thumb code rather than using BX and a mode-switching stub before each
+ PLT entry. This should lead to such calls executing slightly faster.
+ 
+ This option is enabled implicitly for SymbianOS, so there is no need to
+ specify it if you are using that target.
+ 
  @ifclear GENERIC
  @lowersections
  @end ifclear
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.44
diff -c -p -r1.44 armelf.em
*** ld/emultempl/armelf.em	3 Mar 2005 11:52:04 -0000	1.44
--- ld/emultempl/armelf.em	12 Apr 2005 20:57:45 -0000
*************** static int byteswap_code = 0;
*** 32,37 ****
--- 32,38 ----
  static int target1_is_rel = 0${TARGET1_IS_REL};
  static char *target2_type = "${TARGET2_TYPE}";
  static int fix_v4bx = 0;
+ static int use_blx = 0;
  
  static void
  gld${EMULATION_NAME}_before_parse (void)
*************** static void
*** 192,198 ****
  arm_elf_create_output_section_statements (void)
  {
    bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type,
!                                    fix_v4bx);
  }
  
  EOF
--- 193,199 ----
  arm_elf_create_output_section_statements (void)
  {
    bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type,
!                                    fix_v4bx, use_blx);
  }
  
  EOF
*************** PARSE_AND_LIST_PROLOGUE='
*** 206,212 ****
  #define OPTION_TARGET1_REL		303
  #define OPTION_TARGET1_ABS		304
  #define OPTION_TARGET2			305
! #define OPTION_FIX_V4BX                 306
  '
  
  PARSE_AND_LIST_SHORTOPTS=p
--- 207,214 ----
  #define OPTION_TARGET1_REL		303
  #define OPTION_TARGET1_ABS		304
  #define OPTION_TARGET2			305
! #define OPTION_FIX_V4BX			306
! #define OPTION_USE_BLX			307
  '
  
  PARSE_AND_LIST_SHORTOPTS=p
*************** PARSE_AND_LIST_LONGOPTS='
*** 219,224 ****
--- 221,227 ----
    { "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
    { "target2", required_argument, NULL, OPTION_TARGET2},
    { "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
+   { "use-blx", no_argument, NULL, OPTION_USE_BLX},
  '
  
  PARSE_AND_LIST_OPTIONS='
*************** PARSE_AND_LIST_OPTIONS='
*** 228,233 ****
--- 231,237 ----
    fprintf (file, _("     --target1=abs            Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
    fprintf (file, _("     --target2=<type>         Specify definition of R_ARM_TARGET2\n"));
    fprintf (file, _("     --fix-v4bx               Rewrite BX rn as MOV pc, rn for ARMv4\n"));
+   fprintf (file, _("     --use-blx                Enable use of BLX instructions\n"));
  '
  
  PARSE_AND_LIST_ARGS_CASES='
*************** PARSE_AND_LIST_ARGS_CASES='
*** 258,263 ****
--- 262,271 ----
      case OPTION_FIX_V4BX:
        fix_v4bx = 1;
        break;
+ 
+     case OPTION_USE_BLX:
+       use_blx = 1;
+       break;
  '
  
  # We have our own after_open and before_allocation functions, but they call

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