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]

[PATCH, arm] Thumb shared library support: Thumb PLT, etc.


Hi,

This is the second piece of a series of patches to make shared
libraries work on Thumb.  The first (yet unreviewed) patch was a GCC
patch: http://gcc.gnu.org/ml/gcc-patches/2002-07/msg00398.html .

This patch among other things adds a new switch --thumb-plt to
generate Thumb PLT on ARM ELF.  My third patch will handle the
interworking aspects of this new flag.

I ran the GCC testsuite with all combinations of -marm/-mthumb and
/-fPIC.  I also did lots of manual testing especially on the lazy
relocation part as our (LynxOS) ld.so does not support that.  A
slightly different form of this patch has been part of our ld (2.10.1)
for sometime now and underwent extensive testing.

Please apply if OK.
Adam

bfd/ChangeLog:
2002-07-17  Adam Nemet  <anemet@lnxw.com>

	* elf32-arm.h (arm_plt): New global.
	(ARM_PLT_ENTRY_SIZE): Rename PLT_ENTRY_SIZE.
	(THUMB_PLT_ENTRY_SIZE): New macro.
	(PLT_ENTRY_SIZE): Return *_PLT_ENTRY_SIZE depending on arm_plt.
	(elf32_arm_plt0_entry): Rename PLT_ENTRY_SIZE to
	ARM_PLT_ENTRY_SIZE.
	(elf32_arm_plt_entry): Likewise.
	(elf_backend_plt_header_size): Likewise.
	(elf32_thumb_plt0_entry): New global.
	(elf32_arm_finish_dynamic_sections): Use it.
	(elf32_thumb_plt_entry): New global.
	(elf32_arm_finish_dynamic_symbol): Use it.  Account for the PLT
	type when setting GOT entries to &PLT[0].
	(elf32_arm_final_link_relocate, R_ARM_THM_PC22 case): Handle
	relocations against the PLT.
	(elf32_arm_check_relocs, case R_ARM_THM_PC22 case): New case.
	Determine if relocation needs a PLT entry.
	(elf32_arm_adjust_dynamic_symbol): Create PLT entries for Thumb
	functions as well.

	* elflink.h (elf_bfd_final_link): Allow numbers in
	link_info.{init,fini}_function.

ld/ChangeLog:
2002-07-17  Adam Nemet  <anemet@lnxw.com>

	* emultempl/armelf.em: Include elf-bfd.h and elf/arm.h.
	(arm_plt): New extern.
	(gld${EMULATION_NAME}_before_parse): Initialize it.
	(arm_elf_finish): Set the last bit of DT_INIT and DT_FINI
	depending on the type of the function.
	(OPTION_THUMB_PLT): New marco.
	(PARSE_AND_LIST_LONGOPTS): Add --thumb-plt.
	(PARSE_AND_LIST_OPTIONS): Likewise.
	(PARSE_AND_LIST_ARGS_CASES): Likewise.

	* ld.texinfo (ARM): Document --thumb-plt.

Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.87
diff -c -p -r1.87 elf32-arm.h
*** bfd/elf32-arm.h	7 Jul 2002 09:10:40 -0000	1.87
--- bfd/elf32-arm.h	17 Jul 2002 22:30:27 -0000
*************** static enum elf_reloc_type_class elf32_a
*** 110,123 ****
     section.  */
  #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
  
  /* The size in bytes of an entry in the procedure linkage table.  */
! #define PLT_ENTRY_SIZE 16
  
  /* The first entry in a procedure linkage table looks like
     this.  It is set up so that any shared library function that is
     called before the relocation has been set up calls the dynamic
     linker first.  */
! static const bfd_vma elf32_arm_plt0_entry [PLT_ENTRY_SIZE / 4] =
    {
      0xe52de004,	/* str   lr, [sp, #-4]!     */
      0xe59fe010,	/* ldr   lr, [pc, #16]      */
--- 110,129 ----
     section.  */
  #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
  
+ /* Which instruction set should be used when producing the PLT.  Set
+    in ld/emultempl/armelf.em.  */
+ int arm_plt;
+ 
  /* The size in bytes of an entry in the procedure linkage table.  */
! #define ARM_PLT_ENTRY_SIZE 	16
! #define THUMB_PLT_ENTRY_SIZE	20
! #define PLT_ENTRY_SIZE (arm_plt ? ARM_PLT_ENTRY_SIZE : THUMB_PLT_ENTRY_SIZE)
  
  /* The first entry in a procedure linkage table looks like
     this.  It is set up so that any shared library function that is
     called before the relocation has been set up calls the dynamic
     linker first.  */
! static const bfd_vma elf32_arm_plt0_entry [ARM_PLT_ENTRY_SIZE / 4] =
    {
      0xe52de004,	/* str   lr, [sp, #-4]!     */
      0xe59fe010,	/* ldr   lr, [pc, #16]      */
*************** static const bfd_vma elf32_arm_plt0_entr
*** 125,139 ****
      0xe5bef008	/* ldr   pc, [lr, #8]!      */
    };
  
  /* Subsequent entries in a procedure linkage table look like
     this.  */
! static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] =
   {
     0xe59fc004,	/* ldr   ip, [pc, #4]       */
     0xe08fc00c,	/* add   ip, pc, ip         */
     0xe59cf000,	/* ldr   pc, [ip]           */
     0x00000000	/* offset to symbol in got  */
   };
  
  /* The ARM linker needs to keep track of the number of relocs that it
     decides to copy in check_relocs for each symbol.  This is so that
--- 131,178 ----
      0xe5bef008	/* ldr   pc, [lr, #8]!      */
    };
  
+ static const insn16 elf32_thumb_plt0_entry [THUMB_PLT_ENTRY_SIZE / 2] =
+   {
+     0xb500,	/* push    {lr}		    */
+     0xb082,	/* sub     sp, #8	    */
+     0x9000,	/* str     r0, [sp]	    */
+     0x4807,	/* ldr     r0, [pc, #28]    */
+     0x300c,	/* add     r0, #12	    */
+     0x4478,	/* add     r0, pc	    */
+     0x4686,	/* mov     lr, r0	    */
+     0x6800,	/* ldr     r0, [r0]	    */
+     0x9001,	/* str     r0, [sp, #4]	    */
+     0xbd01	/* pop     {r0, pc}	    */
+   };
+ 
  /* Subsequent entries in a procedure linkage table look like
     this.  */
! static const bfd_vma elf32_arm_plt_entry [ARM_PLT_ENTRY_SIZE / 4] =
   {
     0xe59fc004,	/* ldr   ip, [pc, #4]       */
     0xe08fc00c,	/* add   ip, pc, ip         */
     0xe59cf000,	/* ldr   pc, [ip]           */
     0x00000000	/* offset to symbol in got  */
   };
+  
+ /* Note that on ARMv5 and above unlike the ARM PLT entries, the Thumb
+    entry can switch mode depending on the corresponding address in the
+    GOT.  The dynamic linker should set or clear the last bit of the
+    address in the GOT accordingly.  */
+ 
+ static const insn16 elf32_thumb_plt_entry [THUMB_PLT_ENTRY_SIZE / 2] =
+   {
+     0xb082,	/* sub   sp, #8		    */
+     0x9000,	/* str   r0, [sp]	    */
+     0x4802,	/* ldr   r0, [pc, #8]	    */
+     0x4478,	/* add   r0, pc		    */
+     0x4684,	/* mov   ip, r0		    */
+     0x6800,	/* ldr   r0, [r0]	    */
+     0x9001,	/* str   r0, [sp, #4]	    */
+     0xbd01,	/* pop   {r0, pc}	    */
+     0x0000,	/* offset to symbol in got  */
+     0x0000
+   };
  
  /* The ARM linker needs to keep track of the number of relocs that it
     decides to copy in check_relocs for each symbol.  This is so that
*************** elf32_arm_final_link_relocate (howto, in
*** 1407,1412 ****
--- 1446,1459 ----
  	  signed_addend = addend;
  	}
  #endif
+ 
+ 	/* If value is zero then we are linking a shared object and
+ 	   this is a reference to an externally visible symbol.  */
+ 	if (h != NULL && h->plt.offset != (bfd_vma) -1 && value == 0)
+ 	  value = (splt->output_section->vma
+ 		   + splt->output_offset
+ 		   + h->plt.offset);
+ 
  #ifndef OLD_ARM_ABI
  	if (r_type == R_ARM_THM_XPC22)
  	  {
*************** elf32_arm_check_relocs (abfd, info, sec,
*** 2725,2730 ****
--- 2772,2788 ----
  	    h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
  	    break;
  
+ 	  case R_ARM_THM_PC22:
+ 	    /* Since there is no PLT32 for Thumb if we are creating a
+ 	       shared library and this is an externally visible symbol
+ 	       then add it to the PLT.  */
+ 	    if (info->shared && h != NULL && h->dynindx != -1
+ 		&& (! info->symbolic
+ 		    || (h->elf_link_hash_flags
+ 			& ELF_LINK_HASH_DEF_REGULAR) == 0))
+ 	      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ 	    break;
+ 
  	  case R_ARM_ABS32:
  	  case R_ARM_REL32:
  	  case R_ARM_PC24:
*************** elf32_arm_adjust_dynamic_symbol (info, h
*** 2955,2961 ****
    /* If this is a function, put it in the procedure linkage table.  We
       will fill in the contents of the procedure linkage table later,
       when we know the address of the .got section.  */
!   if (h->type == STT_FUNC
        || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
      {
        if (! info->shared
--- 3013,3019 ----
    /* If this is a function, put it in the procedure linkage table.  We
       will fill in the contents of the procedure linkage table later,
       when we know the address of the .got section.  */
!   if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC
        || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
      {
        if (! info->shared
*************** elf32_arm_finish_dynamic_symbol (output_
*** 3345,3369 ****
        got_offset = (plt_index + 3) * 4;
  
        /* Fill in the entry in the procedure linkage table.  */
!       bfd_put_32 (output_bfd, elf32_arm_plt_entry[0],
! 		  splt->contents + h->plt.offset + 0);
!       bfd_put_32 (output_bfd, elf32_arm_plt_entry[1],
! 		  splt->contents + h->plt.offset + 4);
!       bfd_put_32 (output_bfd, elf32_arm_plt_entry[2],
! 		  splt->contents + h->plt.offset + 8);
!       bfd_put_32 (output_bfd,
! 		      (sgot->output_section->vma
! 		       + sgot->output_offset
! 		       + got_offset
! 		       - splt->output_section->vma
! 		       - splt->output_offset
! 		       - h->plt.offset - 12),
  		      splt->contents + h->plt.offset + 12);
  
        /* Fill in the entry in the global offset table.  */
        bfd_put_32 (output_bfd,
  		  (splt->output_section->vma
! 		   + splt->output_offset),
  		  sgot->contents + got_offset);
  
        /* Fill in the entry in the .rel.plt section.  */
--- 3403,3450 ----
        got_offset = (plt_index + 3) * 4;
  
        /* Fill in the entry in the procedure linkage table.  */
!       
!       if (arm_plt)
! 	{
! 	  bfd_put_32 (output_bfd, elf32_arm_plt_entry[0],
! 		      splt->contents + h->plt.offset + 0);
! 	  bfd_put_32 (output_bfd, elf32_arm_plt_entry[1],
! 		      splt->contents + h->plt.offset + 4);
! 	  bfd_put_32 (output_bfd, elf32_arm_plt_entry[2],
! 		      splt->contents + h->plt.offset + 8);
! 	}
!       else
! 	{
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[0],
! 		      splt->contents + h->plt.offset + 0);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[1],
! 		      splt->contents + h->plt.offset + 2);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[2],
! 		      splt->contents + h->plt.offset + 4);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[3],
! 		      splt->contents + h->plt.offset + 6);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[4],
! 		      splt->contents + h->plt.offset + 8);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[5],
! 		      splt->contents + h->plt.offset + 10);
! 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[6],
  		      splt->contents + h->plt.offset + 12);
+ 	  bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt_entry[7],
+ 		      splt->contents + h->plt.offset + 14);
+ 	}
+       bfd_put_32 (output_bfd,
+ 		  (sgot->output_section->vma
+ 		   + sgot->output_offset
+ 		   + got_offset
+ 		   - splt->output_section->vma
+ 		   - splt->output_offset
+ 		   - h->plt.offset - (arm_plt ? 12 : 10)),
+ 		  splt->contents + h->plt.offset + (arm_plt ? 12 : 16));
  
        /* Fill in the entry in the global offset table.  */
        bfd_put_32 (output_bfd,
  		  (splt->output_section->vma
! 		   + splt->output_offset | (arm_plt ? 0 : 1)),
  		  sgot->contents + got_offset);
  
        /* Fill in the entry in the .rel.plt section.  */
*************** elf32_arm_finish_dynamic_sections (outpu
*** 3547,3556 ****
        /* Fill in the first entry in the procedure linkage table.  */
        if (splt->_raw_size > 0)
  	{
! 	  bfd_put_32 (output_bfd, elf32_arm_plt0_entry[0], splt->contents +  0);
! 	  bfd_put_32 (output_bfd, elf32_arm_plt0_entry[1], splt->contents +  4);
! 	  bfd_put_32 (output_bfd, elf32_arm_plt0_entry[2], splt->contents +  8);
! 	  bfd_put_32 (output_bfd, elf32_arm_plt0_entry[3], splt->contents + 12);
  	}
  
        /* UnixWare sets the entsize of .plt to 4, although that doesn't
--- 3628,3667 ----
        /* Fill in the first entry in the procedure linkage table.  */
        if (splt->_raw_size > 0)
  	{
! 	  if (arm_plt)
! 	    {
! 	      bfd_put_32 (output_bfd, elf32_arm_plt0_entry[0],
! 			  splt->contents +  0);
! 	      bfd_put_32 (output_bfd, elf32_arm_plt0_entry[1],
! 			  splt->contents +  4);
! 	      bfd_put_32 (output_bfd, elf32_arm_plt0_entry[2],
! 			  splt->contents +  8);
! 	      bfd_put_32 (output_bfd, elf32_arm_plt0_entry[3],
! 			  splt->contents + 12);
! 	    }
! 	  else
! 	    {
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[0],
! 			  splt->contents + 0);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[1],
! 			  splt->contents + 2);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[2],
! 			  splt->contents + 4);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[3],
! 			  splt->contents + 6);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[4],
! 			  splt->contents + 8);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[5],
! 			  splt->contents + 10);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[6],
! 			  splt->contents + 12);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[7],
! 			  splt->contents + 14);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[8],
! 			  splt->contents + 16);
! 	      bfd_put_16 (output_bfd, (bfd_vma) elf32_thumb_plt0_entry[9],
! 			  splt->contents + 18);
! 	    }
  	}
  
        /* UnixWare sets the entsize of .plt to 4, although that doesn't
*************** elf32_arm_reloc_type_class (rela)
*** 3641,3646 ****
  #endif
  
  #define elf_backend_got_header_size	12
! #define elf_backend_plt_header_size	PLT_ENTRY_SIZE
  
  #include "elf32-target.h"
--- 3752,3757 ----
  #endif
  
  #define elf_backend_got_header_size	12
! #define elf_backend_plt_header_size	ARM_PLT_ENTRY_SIZE
  
  #include "elf32-target.h"
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.177
diff -c -p -r1.177 elflink.h
*** bfd/elflink.h	16 Jul 2002 12:31:35 -0000	1.177
--- bfd/elflink.h	17 Jul 2002 22:30:28 -0000
*************** elf_bfd_final_link (abfd, info)
*** 5662,5667 ****
--- 5662,5681 ----
  
  		    elf_swap_dyn_out (dynobj, &dyn, dyncon);
  		  }
+ 		else
+ 		  {
+ 		    bfd_vma val;
+ 		    CONST char *send;
+ 
+ 		    /* We couldn't find the entry symbol.  Try parsing it as a
+ 		       number.  */
+ 		    val = bfd_scan_vma (name, &send, 0);
+ 		    if (*send == '\0')
+ 		      {
+ 			dyn.d_un.d_val = val;
+ 			elf_swap_dyn_out (dynobj, &dyn, dyncon);
+ 		      }
+ 		  }
  	      }
  	      break;
  
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.27
diff -c -p -r1.27 armelf.em
*** ld/emultempl/armelf.em	1 Jul 2002 08:07:31 -0000	1.27
--- ld/emultempl/armelf.em	17 Jul 2002 22:30:28 -0000
***************
*** 24,33 ****
  #
  cat >>e${EMULATION_NAME}.c <<EOF
  
  static int no_pipeline_knowledge = 0;
  static char *thumb_entry_symbol = NULL;
  static bfd *bfd_for_interwork;
! 
  
  static void
  gld${EMULATION_NAME}_before_parse ()
--- 24,36 ----
  #
  cat >>e${EMULATION_NAME}.c <<EOF
  
+ #include "elf-bfd.h"
+ #include "elf/arm.h"
+ 
  static int no_pipeline_knowledge = 0;
  static char *thumb_entry_symbol = NULL;
  static bfd *bfd_for_interwork;
! extern int arm_plt;
  
  static void
  gld${EMULATION_NAME}_before_parse ()
*************** gld${EMULATION_NAME}_before_parse ()
*** 37,42 ****
--- 40,46 ----
  #endif /* not TARGET_ */
    config.dynamic_link = ${DYNAMIC_LINK-true};
    config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
+   arm_plt = 1;
  }
  
  static void arm_elf_after_open PARAMS ((void));
*************** static void
*** 138,185 ****
  arm_elf_finish ()
  {
    struct bfd_link_hash_entry * h;
  
    /* Call the elf32.em routine.  */
    gld${EMULATION_NAME}_finish ();
  
!   if (thumb_entry_symbol == NULL)
!     return;
!   
!   h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
! 			    false, false, true);
  
    if (h != (struct bfd_link_hash_entry *) NULL
        && (h->type == bfd_link_hash_defined
  	  || h->type == bfd_link_hash_defweak)
        && h->u.def.section->output_section != NULL)
      {
        static char buffer[32];
        bfd_vma val;
!       
!       /* Special procesing is required for a Thumb entry symbol.  The
! 	 bottom bit of its address must be set.  */
        val = (h->u.def.value
  	     + bfd_get_section_vma (output_bfd,
  				    h->u.def.section->output_section)
  	     + h->u.def.section->output_offset);
!       
        val |= 1;
  
!       /* Now convert this value into a string and store it in entry_symbol
!          where the lang_finish() function will pick it up.  */
        buffer[0] = '0';
        buffer[1] = 'x';
!       
        sprintf_vma (buffer + 2, val);
  
!       if (entry_symbol.name != NULL && entry_from_cmdline)
! 	einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
! 	       thumb_entry_symbol, entry_symbol.name);
!       entry_symbol.name = buffer;
      }
-   else
-     einfo (_("%P: warning: connot find thumb start symbol %s\n"),
- 	   thumb_entry_symbol);
  }
  
  EOF
--- 142,256 ----
  arm_elf_finish ()
  {
    struct bfd_link_hash_entry * h;
+   struct elf_link_hash_entry * eh;
  
    /* Call the elf32.em routine.  */
    gld${EMULATION_NAME}_finish ();
  
!   if (thumb_entry_symbol != NULL)
!     {
!       h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
! 				false, false, true);
! 
!       if (h != (struct bfd_link_hash_entry *) NULL
! 	  && (h->type == bfd_link_hash_defined
! 	      || h->type == bfd_link_hash_defweak)
! 	  && h->u.def.section->output_section != NULL)
! 	{
! 	  static char buffer[32];
! 	  bfd_vma val;
!       
! 	  /* Special procesing is required for a Thumb entry symbol.  The
! 	     bottom bit of its address must be set.  */
! 	  val = (h->u.def.value
! 		 + bfd_get_section_vma (output_bfd,
! 					h->u.def.section->output_section)
! 		 + h->u.def.section->output_offset);
!       
! 	  val |= 1;
! 
! 	  /* Now convert this value into a string and store it in entry_symbol
! 	     where the lang_finish() function will pick it up.  */
! 	  buffer[0] = '0';
! 	  buffer[1] = 'x';
!       
! 	  sprintf_vma (buffer + 2, val);
! 
! 	  if (entry_symbol.name != NULL && entry_from_cmdline)
! 	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
! 		   thumb_entry_symbol, entry_symbol.name);
! 	  entry_symbol.name = buffer;
! 	}
!       else
! 	einfo (_("%P: warning: connot find thumb start symbol %s\n"),
! 	       thumb_entry_symbol);
!     }
! 
!   /* If init is a Thumb function set the LSB.  */
!   h = bfd_link_hash_lookup (link_info.hash, link_info.init_function, false,
! 			    false, true);
!   eh = (struct elf_link_hash_entry *)h;
  
    if (h != (struct bfd_link_hash_entry *) NULL
        && (h->type == bfd_link_hash_defined
  	  || h->type == bfd_link_hash_defweak)
+       && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC
        && h->u.def.section->output_section != NULL)
      {
        static char buffer[32];
        bfd_vma val;
! 
!       /* Special procesing is required for a Thumb symbol.  The bottom
! 	 bit of its address must be set.  */
        val = (h->u.def.value
  	     + bfd_get_section_vma (output_bfd,
  				    h->u.def.section->output_section)
  	     + h->u.def.section->output_offset);
! 
        val |= 1;
  
!       /* Now convert this value into a string and store it in
! 	 init_function where the elf_bfd_final_link() function will
! 	 pick it up.  */
        buffer[0] = '0';
        buffer[1] = 'x';
! 
        sprintf_vma (buffer + 2, val);
+       link_info.init_function = buffer;
+     }
+ 
+   /* If fini is a Thumb function set the LSB.  */
+   h = bfd_link_hash_lookup (link_info.hash, link_info.fini_function, false,
+ 			    false, true);
+   eh = (struct elf_link_hash_entry *)h;
  
!   if (h != (struct bfd_link_hash_entry *) NULL
!       && (h->type == bfd_link_hash_defined
! 	  || h->type == bfd_link_hash_defweak)
!       && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC
!       && h->u.def.section->output_section != NULL)
!     {
!       static char buffer[32];
!       bfd_vma val;
! 
!       /* Special procesing is required for a Thumb symbol.  The bottom
! 	 bit of its address must be set.  */
!       val = (h->u.def.value
! 	     + bfd_get_section_vma (output_bfd,
! 				    h->u.def.section->output_section)
! 	     + h->u.def.section->output_offset);
! 
!       val |= 1;
! 
!       /* Now convert this value into a string and store it in
! 	 fini_function where the elf_bfd_final_link() function will
! 	 pick it up.  */
!       buffer[0] = '0';
!       buffer[1] = 'x';
! 
!       sprintf_vma (buffer + 2, val);
!       link_info.fini_function = buffer;
      }
  }
  
  EOF
*************** EOF
*** 189,194 ****
--- 260,266 ----
  #
  PARSE_AND_LIST_PROLOGUE='
  #define OPTION_THUMB_ENTRY		301
+ #define OPTION_THUMB_PLT		302
  '
  
  # Note we add 'n' to the short option list in order to prevent
*************** PARSE_AND_LIST_SHORTOPTS=pn
*** 201,211 ****
--- 273,285 ----
  PARSE_AND_LIST_LONGOPTS='
    { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
    { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+   { "thumb-plt", no_argument, NULL, OPTION_THUMB_PLT},
  '
  
  PARSE_AND_LIST_OPTIONS='
    fprintf (file, _("  -p --no-pipeline-knowledge  Stop the linker knowing about the pipeline length\n"));
    fprintf (file, _("     --thumb-entry=<sym>      Set the entry point to be Thumb symbol <sym>\n"));
+   fprintf (file, _("     --thumb-plt              Generate Thumb PLT section\n"));
  '
  
  PARSE_AND_LIST_ARGS_CASES='
*************** PARSE_AND_LIST_ARGS_CASES='
*** 215,220 ****
--- 289,298 ----
  
      case OPTION_THUMB_ENTRY:
        thumb_entry_symbol = optarg;
+       break;
+ 
+     case OPTION_THUMB_PLT:
+       arm_plt = 0;
        break;
  '
  
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.71
diff -c -p -r1.71 ld.texinfo
*** ld/ld.texinfo	15 Jul 2002 02:23:26 -0000	1.71
--- ld/ld.texinfo	17 Jul 2002 22:30:29 -0000
*************** But it also sets the bottom bit of the a
*** 4494,4499 ****
--- 4494,4506 ----
  branched to using a BX instruction, and the program will start
  executing in Thumb mode straight away.
  
+ @cindex thumb PLT
+ @cindex PLT, thumb
+ @kindex --thumb-plt
+ For ELF, the @samp{--thumb-plt} switch forces @command{ld} to use the
+ Thumb instruction set to generate the PLT.  This allows building pure
+ Thumb shared libraries.
+ 
  @node HPPA ELF32
  @section @command{ld} and HPPA 32-bit ELF support
  @cindex HPPA multiple sub-space stubs


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