PATCH for small plt support via "ld -z now"

Graeme Peterson gp@qnx.com
Thu Aug 15 13:01:00 GMT 2002


Hi, all.

Here is a patch for your consideration for small plt stubs for
elf32-sh.  

I am on holiday for the next 2 weeks, so if anyone has any
objections, please fix them and submit it, or let me know and
I will do so when I am back.

The SHMEDIA does not have small stub support, but I tried to clean
things up and make it so that it would work.  I have not been able 
to try this on anything other than sh-nto, so if anyone can and feels
inclined, that would be great.

Thanks.
GP

===============================================
ChangeLog for bfd/elf32-sh.c

2002-08-15  Graeme Peterson  <gp@qnx.com>

    * elf32-sh.c: Add support for small plt entries for 32 bit sh.
    Add macro BFD_PUT_VAL to replace bfd_put_32 and movi_shori_putval
    calls with identical parameters wrapped in #ifdef INCLUDE_SHMEDIA.

                  

-------------- next part --------------
*** src/bfd/elf32-sh.c	Sun Jul  7 05:10:39 2002
--- src.qnx/bfd/elf32-sh.c	Thu Aug 15 15:09:39 2002
*************** static const bfd_byte *elf_sh_plt0_entry
*** 3071,3076 ****
--- 3071,3089 ----
  static const bfd_byte *elf_sh_plt_entry;
  static const bfd_byte *elf_sh_pic_plt_entry;
  
+ #define ELF_SH_PLT_ENTRY(obfd, info) \
+   (bfd_big_endian (obfd)             \
+     ? elf_sh_plt_entry_be            \
+     : elf_sh_plt_entry_le);
+ 
+ #define ELF_SH_PIC_PLT_ENTRY(obfd, info) \
+   (bfd_big_endian (obfd)                 \
+     ? elf_sh_pic_plt_entry_be            \
+     : elf_sh_pic_plt_entry_le);
+ 
+ /* No small plt's for SHMEDIA yet, so lazy linking is true. */
+ #define LAZY_LINKING(info) 1
+ 
  /* Return size of a PLT entry.  */
  #define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
  
*************** static const bfd_byte *elf_sh_pic_plt_en
*** 3089,3094 ****
--- 3102,3111 ----
  /* Return offset of the relocation in PLT entry.  */
  #define elf_sh_plt_reloc_offset(info) (info->shared ? 52 : 44)
  
+ /* This macro is to clean up ifdef's that wrapped bfd_put_32's
+    and movi_shori_putval's that had the same parameters.  */
+ #define BFD_PUT_VAL movi_shori_putval
+ 
  inline static void
  movi_shori_putval (output_bfd, value, addr)
       bfd *output_bfd;
*************** static const bfd_byte elf_sh_pic_plt_ent
*** 3321,3332 ****
  };
  #endif /* old style PLT entries.  */
  
  static const bfd_byte *elf_sh_plt0_entry;
  static const bfd_byte *elf_sh_plt_entry;
  static const bfd_byte *elf_sh_pic_plt_entry;
  
  /* Return size of a PLT entry.  */
! #define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
  
  /* Return offset of the PLT0 address in an absolute PLT entry.  */
  #define elf_sh_plt_plt0_offset(info) 16
--- 3338,3409 ----
  };
  #endif /* old style PLT entries.  */
  
+ /* Small PLT stuff without lazy binding.  */
+ 
+ #define SMALL_PLT_ENTRY_SIZE   12
+ #define LAZY_LINKING(info)  (! (info->flags & DF_BIND_NOW))
+ 
+ static const bfd_byte elf_sh_small_plt_entry_be[SMALL_PLT_ENTRY_SIZE] =
+ {
+   0xd1, 0x01,   /* mov.l 0f,r1 */
+   0x61, 0x12,   /* mov.l @r1,r1 */
+   0x41, 0x2b,   /* jmp @r1 */
+   0x00, 0x09,   /* nop */
+   0, 0, 0, 0,   /* 0: replaced with address of this symbol in .got.  */
+ };
+ 
+ static const bfd_byte elf_sh_small_plt_entry_le[SMALL_PLT_ENTRY_SIZE] =
+ {
+   0x01, 0xd1,   /* mov.l 0f,r1 */
+   0x12, 0x61,   /* mov.l @r1,r1 */
+   0x2b, 0x41,   /* jmp @r1 */
+   0x09, 0x00,   /* nop */
+   0, 0, 0, 0,   /* 0: replaced with address of this symbol in .got.  */
+ };
+ 
+ static const bfd_byte elf_sh_pic_small_plt_entry_be[SMALL_PLT_ENTRY_SIZE] =
+ {
+   0xd0, 0x01,   /* mov.l 1f,r0 */
+   0x00, 0xce,   /* mov.l @(r0,r12),r0 */
+   0x40, 0x2b,   /* jmp @r0 */
+   0x00, 0x09,   /*  nop */
+   0, 0, 0, 0,   /* 1: replaced with offset of this symbol in .got.  */
+ };
+ 
+ static const bfd_byte elf_sh_pic_small_plt_entry_le[SMALL_PLT_ENTRY_SIZE] =
+ {
+   0x01, 0xd0,   /* mov.l 1f,r0 */
+   0xce, 0x00,   /* mov.l @(r0,r12),r0 */
+   0x2b, 0x40,   /* jmp @r0 */
+   0x09, 0x00,   /*  nop */
+   0, 0, 0, 0,   /* 1: replaced with offset of this symbol in .got.  */
+ };
+ 
  static const bfd_byte *elf_sh_plt0_entry;
  static const bfd_byte *elf_sh_plt_entry;
  static const bfd_byte *elf_sh_pic_plt_entry;
  
+ #define ELF_SH_PLT_ENTRY(obfd, info) \
+   (bfd_big_endian (obfd)             \
+     ? LAZY_LINKING(info)             \
+       ? elf_sh_plt_entry_be          \
+       : elf_sh_small_plt_entry_be    \
+     : LAZY_LINKING(info)             \
+       ? elf_sh_plt_entry_le          \
+       : elf_sh_small_plt_entry_le)
+ 
+ #define ELF_SH_PIC_PLT_ENTRY(obfd, info) \
+   (bfd_big_endian (obfd)                 \
+     ? LAZY_LINKING(info)                 \
+       ? elf_sh_pic_plt_entry_be          \
+       : elf_sh_pic_small_plt_entry_be    \
+     : LAZY_LINKING(info)                 \
+       ? elf_sh_pic_plt_entry_le          \
+       : elf_sh_pic_small_plt_entry_le)
+ 
  /* Return size of a PLT entry.  */
! #define elf_sh_sizeof_plt(info) \
!   (LAZY_LINKING(info) ? PLT_ENTRY_SIZE : SMALL_PLT_ENTRY_SIZE)
  
  /* Return offset of the PLT0 address in an absolute PLT entry.  */
  #define elf_sh_plt_plt0_offset(info) 16
*************** static const bfd_byte *elf_sh_pic_plt_en
*** 3338,3350 ****
  #define elf_sh_plt0_gotid_offset(info) 24
  
  /* Return offset of the tempoline in PLT entry */
! #define elf_sh_plt_temp_offset(info) 8
  
  /* Return offset of the symbol in PLT entry.  */
! #define elf_sh_plt_symbol_offset(info) 20
  
  /* Return offset of the relocation in PLT entry.  */
  #define elf_sh_plt_reloc_offset(info) 24
  #endif
  
  /* The sh linker needs to keep track of the number of relocs that it
--- 3415,3431 ----
  #define elf_sh_plt0_gotid_offset(info) 24
  
  /* Return offset of the tempoline in PLT entry */
! #define elf_sh_plt_temp_offset(info) (LAZY_LINKING(info) ? 8 : 0)
  
  /* Return offset of the symbol in PLT entry.  */
! #define elf_sh_plt_symbol_offset(info) (LAZY_LINKING(info) ? 20 : 8)
  
  /* Return offset of the relocation in PLT entry.  */
  #define elf_sh_plt_reloc_offset(info) 24
+ 
+ /* This macro is to clean up ifdef's that wrapped bfd_put_32's
+    and movi_shori_putval's that had the same parameters.  */
+ #define BFD_PUT_VAL bfd_put_32
  #endif
  
  /* The sh linker needs to keep track of the number of relocs that it
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5470,5477 ****
        /* Get the index in the procedure linkage table which
  	 corresponds to this symbol.  This is the index of this symbol
  	 in all the symbols for which we are making plt entries.  The
! 	 first entry in the procedure linkage table is reserved.  */
!       plt_index = h->plt.offset / elf_sh_sizeof_plt (info) - 1;
  
        /* Get the offset into the .got table of the entry that
  	 corresponds to this function.  Each .got entry is 4 bytes.
--- 5551,5563 ----
        /* Get the index in the procedure linkage table which
  	 corresponds to this symbol.  This is the index of this symbol
  	 in all the symbols for which we are making plt entries.  The
! 	 first entry in the procedure linkage table is reserved.  Take
! 	 into account that first .plt entry is the large size */
! 
!       if (! LAZY_LINKING(info))
!         plt_index = (h->plt.offset - PLT_ENTRY_SIZE)/ elf_sh_sizeof_plt (info);
!       else
!         plt_index = h->plt.offset / elf_sh_sizeof_plt (info) - 1;
  
        /* Get the offset into the .got table of the entry that
  	 corresponds to this function.  Each .got entry is 4 bytes.
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5487,5566 ****
  	{
  	  if (elf_sh_plt_entry == NULL)
  	    {
! 	      elf_sh_plt_entry = (bfd_big_endian (output_bfd) ?
! 				  elf_sh_plt_entry_be : elf_sh_plt_entry_le);
  	    }
  	  memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
  		  elf_sh_sizeof_plt (info));
! #ifdef INCLUDE_SHMEDIA
! 	  movi_shori_putval (output_bfd,
! 			     (sgot->output_section->vma
! 			      + sgot->output_offset
! 			      + got_offset),
! 			     (splt->contents + h->plt.offset
! 			      + elf_sh_plt_symbol_offset (info)));
! 
! 	  movi_shori_putval (output_bfd,
! 			     (splt->output_section->vma + splt->output_offset),
! 			     (splt->contents + h->plt.offset
! 			      + elf_sh_plt_plt0_offset (info)));
! #else
! 	  bfd_put_32 (output_bfd,
! 		      (sgot->output_section->vma
  		       + sgot->output_offset
  		       + got_offset),
  		      (splt->contents + h->plt.offset
  		       + elf_sh_plt_symbol_offset (info)));
  
! 	  bfd_put_32 (output_bfd,
! 		      (splt->output_section->vma + splt->output_offset),
! 		      (splt->contents + h->plt.offset
! 		       + elf_sh_plt_plt0_offset (info)));
! #endif
  	}
        else
  	{
  	  if (elf_sh_pic_plt_entry == NULL)
  	    {
! 	      elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! 				      elf_sh_pic_plt_entry_be :
! 				      elf_sh_pic_plt_entry_le);
  	    }
  	  memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
  		  elf_sh_sizeof_plt (info));
! #ifdef INCLUDE_SHMEDIA
! 	  movi_shori_putval (output_bfd, got_offset,
! 			     (splt->contents + h->plt.offset
! 			      + elf_sh_plt_symbol_offset (info)));
! #else
! 	  bfd_put_32 (output_bfd, got_offset,
  		      (splt->contents + h->plt.offset
  		       + elf_sh_plt_symbol_offset (info)));
- #endif
  	}
  
  #ifdef GOT_BIAS
        got_offset += GOT_BIAS;
  #endif
  
! #ifdef INCLUDE_SHMEDIA
!       movi_shori_putval (output_bfd,
! 			 plt_index * sizeof (Elf32_External_Rela),
! 			 (splt->contents + h->plt.offset
! 			  + elf_sh_plt_reloc_offset (info)));
! #else
!       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
! 		  (splt->contents + h->plt.offset
! 		   + elf_sh_plt_reloc_offset (info)));
! #endif
  
        /* Fill in the entry in the global offset table.  */
!       bfd_put_32 (output_bfd,
! 		  (splt->output_section->vma
! 		   + splt->output_offset
! 		   + h->plt.offset
! 		   + elf_sh_plt_temp_offset (info)),
! 		  sgot->contents + got_offset);
  
        /* Fill in the entry in the .rela.plt section.  */
        rel.r_offset = (sgot->output_section->vma
--- 5573,5626 ----
  	{
  	  if (elf_sh_plt_entry == NULL)
  	    {
! 	      elf_sh_plt_entry = ELF_SH_PLT_ENTRY(output_bfd, info);
  	    }
  	  memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
  		  elf_sh_sizeof_plt (info));
! 	  BFD_PUT_VAL (output_bfd,
! 	 	      (sgot->output_section->vma
  		       + sgot->output_offset
  		       + got_offset),
  		      (splt->contents + h->plt.offset
  		       + elf_sh_plt_symbol_offset (info)));
  
! 	  if (LAZY_LINKING(info))
! 	    BFD_PUT_VAL (output_bfd,
! 		        (splt->output_section->vma + splt->output_offset),
! 		        (splt->contents + h->plt.offset
! 		         + elf_sh_plt_plt0_offset (info)));
  	}
        else
  	{
  	  if (elf_sh_pic_plt_entry == NULL)
  	    {
! 	      elf_sh_pic_plt_entry = ELF_SH_PIC_PLT_ENTRY(output_bfd, info);
  	    }
  	  memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
  		  elf_sh_sizeof_plt (info));
! 	  BFD_PUT_VAL (output_bfd, got_offset,
  		      (splt->contents + h->plt.offset
  		       + elf_sh_plt_symbol_offset (info)));
  	}
  
  #ifdef GOT_BIAS
        got_offset += GOT_BIAS;
  #endif
  
!       if (LAZY_LINKING(info))
!         BFD_PUT_VAL (output_bfd, plt_index * sizeof (Elf32_External_Rela),
! 		    (splt->contents + h->plt.offset
! 		     + elf_sh_plt_reloc_offset (info)));
  
        /* Fill in the entry in the global offset table.  */
! 
!       if (LAZY_LINKING(info))
!         bfd_put_32 (output_bfd,
! 		    (splt->output_section->vma
! 		     + splt->output_offset
! 		     + h->plt.offset
! 		     + elf_sh_plt_temp_offset (info)),
! 		    sgot->contents + got_offset);
  
        /* Fill in the entry in the .rela.plt section.  */
        rel.r_offset = (sgot->output_section->vma
*************** sh_elf_finish_dynamic_sections (output_b
*** 5754,5762 ****
  	    {
  	      if (elf_sh_pic_plt_entry == NULL)
  		{
! 		  elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! 					  elf_sh_pic_plt_entry_be :
! 					  elf_sh_pic_plt_entry_le);
  		}
  	      memcpy (splt->contents, elf_sh_pic_plt_entry,
  		      elf_sh_sizeof_plt (info));
--- 5814,5820 ----
  	    {
  	      if (elf_sh_pic_plt_entry == NULL)
  		{
! 		  elf_sh_pic_plt_entry = ELF_SH_PIC_PLT_ENTRY(output_bfd, info);
  		}
  	      memcpy (splt->contents, elf_sh_pic_plt_entry,
  		      elf_sh_sizeof_plt (info));


More information about the Binutils mailing list