public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] (version 2) Change MIPS linker stubs to allow for more than  2^15 symbols.
@ 2006-06-08 23:03 David Daney
  2006-06-08 23:12 ` Thiemo Seufer
                   ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: David Daney @ 2006-06-08 23:03 UTC (permalink / raw)
  To: binutils; +Cc: Richard Sandiford, Thiemo Seufer, Daniel Jacobowitz

[-- Attachment #1: Type: text/plain, Size: 2022 bytes --]

As noted in this thread:

http://sourceware.org/ml/binutils/2006-06/msg00086.html

The mips linker would not reliably allow for more than 2^15 dynamic 
symbols.  This prevents GCC's libgcj java runtime library from being 
correctly linked.

This new version of the patch fixes allows up to 2^31 - 1 dynamic 
symbols by modifying linker stub generation.

If there are more than 2^16 dynamic symbols (as is the case for 
libgcj.so) a 20 byte stub is used.

For objects with 2^16 or fewer dynamic symbols, a stub of the original 
16 byte size is used.  This case is further divided in to two sub-cases: 
For an index value less than 2^15 the original sign extending stub is 
used, for index values of 2^15 through 2^16 a new non sign extending 
(but still 16 byte) stub is used.  The idea is to make the stub as small 
as possible as well as not change its form unless necessary.  It is 
thought that this strategy will decrease the chance of breaking existing 
tools.

Tested mipsel-linux cross build running on i686-pc-linux-gnu with make 
-k check showing no regressions.  Also tested that java executables from 
GCC-4.2 now are able to run.  Small objects still have the original 16 
byte stub, libgcj.so.7.0.0 uses the 20 byte stub.

Perhaps others could test on mips64 and/or big-endian systems.

OK to commit?

I know it is a bit late in the game, but how about for 2.17?  It would 
be nice to say that gcc-4.2 can be used with an official binutils release.

David Daney

2006-06-08  David Daney  <ddaney@avtrex.com>

	* elfxx-mips.c (STUB_LI16): Removed.
	(STUB_LUI): New macro.
	(STUB_LI16U): Ditto.
	(STUB_LI16S): Ditto.
	(MIPS_FUNCTION_STUB_SIZE): Rewrote to take info parameter.
	(_bfd_mips_elf_adjust_dynamic_symbol): Pass info parameter to
	MIPS_FUNCTION_STUB_SIZE.
	(_bfd_mips_elf_always_size_sections): Ditto.
	(_bfd_mips_elf_size_dynamic_sections): Ditto.
	(_bfd_mips_elf_finish_dynamic_sections): Ditto.
	(_bfd_mips_elf_finish_dynamic_symbol): Rewrote stub generation
	to allow larger symbol table indexes.

[-- Attachment #2: mips-stubs.diff.txt --]
[-- Type: text/plain, Size: 7963 bytes --]

Index: elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.169
diff -c -p -r1.169 elfxx-mips.c
*** elfxx-mips.c	22 May 2006 15:06:22 -0000	1.169
--- elfxx-mips.c	8 Jun 2006 21:50:00 -0000
*************** static bfd *reldyn_sorting_bfd;
*** 623,642 ****
  #define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
  
  /* Instructions which appear in a stub.  */
! #define STUB_LW(abfd)						\
!   ((ABI_64_P (abfd)  						\
!     ? 0xdf998010		/* ld t9,0x8010(gp) */		\
!     : 0x8f998010))              /* lw t9,0x8010(gp) */
! #define STUB_MOVE(abfd)                                         \
!    ((ABI_64_P (abfd)						\
!      ? 0x03e0782d		/* daddu t7,ra */		\
!      : 0x03e07821))		/* addu t7,ra */
! #define STUB_JALR 0x0320f809	/* jalr t9,ra */
! #define STUB_LI16(abfd)                                         \
!   ((ABI_64_P (abfd)						\
!    ? 0x64180000			/* daddiu t8,zero,0 */		\
!    : 0x24180000))		/* addiu t8,zero,0 */
! #define MIPS_FUNCTION_STUB_SIZE (16)
  
  /* The name of the dynamic interpreter.  This is put in the .interp
     section.  */
--- 623,648 ----
  #define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
  
  /* Instructions which appear in a stub.  */
! #define STUB_LW(abfd)							\
!   ((ABI_64_P (abfd)							\
!     ? 0xdf998010				/* ld t9,0x8010(gp) */	\
!     : 0x8f998010))              		/* lw t9,0x8010(gp) */
! #define STUB_MOVE(abfd)							\
!    ((ABI_64_P (abfd)							\
!      ? 0x03e0782d				/* daddu t7,ra */	\
!      : 0x03e07821))				/* addu t7,ra */
! #define STUB_LUI(VAL) (0x3c180000 + (VAL))	/* lui t8,VAL */
! #define STUB_JALR 0x0320f809			/* jalr t9,ra */
! #define STUB_LI16U(VAL) (0x34180000 + (VAL))	/* ori t8,zero,VAL unsigned*/
! #define STUB_LI16S(abfd, VAL)						\
!    ((ABI_64_P (abfd)							\
!     ? (0x64180000 + (VAL))	/* daddiu t8,zero,VAL sign extended */	\
!     : (0x24180000 + (VAL))))	/* addiu t8,zero,VAL sign extended */
! 
! #define MIPS_FUNCTION_STUB_SIZE(INFO) \
!   (elf_hash_table (INFO)->dynsymcount > 65536 ? 20 : 16)
! 
! #define MIPS_FUNCTION_STUB_MAX_SIZE 20
  
  /* The name of the dynamic interpreter.  This is put in the .interp
     section.  */
*************** _bfd_mips_elf_adjust_dynamic_symbol (str
*** 6877,6883 ****
  	  h->plt.offset = s->size;
  
  	  /* Make room for this stub code.  */
! 	  s->size += MIPS_FUNCTION_STUB_SIZE;
  
  	  /* The last half word of the stub will be filled with the index
  	     of this symbol in .dynsym section.  */
--- 6883,6889 ----
  	  h->plt.offset = s->size;
  
  	  /* Make room for this stub code.  */
! 	  s->size += MIPS_FUNCTION_STUB_SIZE (info);
  
  	  /* The last half word of the stub will be filled with the index
  	     of this symbol in .dynsym section.  */
*************** _bfd_mips_elf_always_size_sections (bfd 
*** 7142,7148 ****
    /* In the worst case, we'll get one stub per dynamic symbol, plus
       one to account for the dummy entry at the end required by IRIX
       rld.  */
!   loadable_size += MIPS_FUNCTION_STUB_SIZE * (i + 1);
  
    if (htab->is_vxworks)
      /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
--- 7148,7154 ----
    /* In the worst case, we'll get one stub per dynamic symbol, plus
       one to account for the dummy entry at the end required by IRIX
       rld.  */
!   loadable_size += MIPS_FUNCTION_STUB_SIZE (info) * (i + 1);
  
    if (htab->is_vxworks)
      /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
*************** _bfd_mips_elf_size_dynamic_sections (bfd
*** 7360,7366 ****
  	{
  	  /* IRIX rld assumes that the function stub isn't at the end
  	     of .text section. So put a dummy. XXX  */
! 	  s->size += MIPS_FUNCTION_STUB_SIZE;
  	}
        else if (! info->shared
  	       && ! mips_elf_hash_table (info)->use_rld_obj_head
--- 7366,7372 ----
  	{
  	  /* IRIX rld assumes that the function stub isn't at the end
  	     of .text section. So put a dummy. XXX  */
! 	  s->size += MIPS_FUNCTION_STUB_SIZE (info);
  	}
        else if (! info->shared
  	       && ! mips_elf_hash_table (info)->use_rld_obj_head
*************** _bfd_mips_elf_finish_dynamic_symbol (bfd
*** 7997,8009 ****
    asection *sgot;
    struct mips_got_info *g, *gg;
    const char *name;
  
    dynobj = elf_hash_table (info)->dynobj;
  
    if (h->plt.offset != MINUS_ONE)
      {
        asection *s;
!       bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
  
        /* This symbol has a stub.  Set it up.  */
  
--- 8003,8016 ----
    asection *sgot;
    struct mips_got_info *g, *gg;
    const char *name;
+   int idx;
  
    dynobj = elf_hash_table (info)->dynobj;
  
    if (h->plt.offset != MINUS_ONE)
      {
        asection *s;
!       bfd_byte stub[MIPS_FUNCTION_STUB_MAX_SIZE];
  
        /* This symbol has a stub.  Set it up.  */
  
*************** _bfd_mips_elf_finish_dynamic_symbol (bfd
*** 8013,8030 ****
  				   MIPS_ELF_STUB_SECTION_NAME (dynobj));
        BFD_ASSERT (s != NULL);
  
!       /* FIXME: Can h->dynindx be more than 64K?  */
!       if (h->dynindx & 0xffff0000)
  	return FALSE;
  
        /* Fill the stub.  */
!       bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub);
!       bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + 4);
!       bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
!       bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub + 12);
  
        BFD_ASSERT (h->plt.offset <= s->size);
!       memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
  
        /* Mark the symbol as undefined.  plt.offset != -1 occurs
  	 only for the referenced symbol.  */
--- 8020,8061 ----
  				   MIPS_ELF_STUB_SECTION_NAME (dynobj));
        BFD_ASSERT (s != NULL);
  
!       BFD_ASSERT ((MIPS_FUNCTION_STUB_SIZE (info) == 20)
!                   || (h->dynindx <= 65536));
! 
!       /* Values up to 2^31 - 1 are allowed.  Larger values would cause
!        * sign extension at runtime in the stub, resulting in a negative
!        * index value.
!        */
!       if (h->dynindx & 0x80000000)
  	return FALSE;
  
        /* Fill the stub.  */
!       idx = 0;
!       bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub + idx);
!       idx += 4;
!       bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
!       idx += 4;
!       if (MIPS_FUNCTION_STUB_SIZE (info) == 20)
!         {
!           bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16 ) & 0xffff),
!                       stub + idx);
!           idx += 4;
!         }
!       bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
!       idx += 4;
  
+       /* If a large stub is not required *and* sign extension is not a
+        * problem, then use legacy code in the stub. */
+       if ((MIPS_FUNCTION_STUB_SIZE (info) == 20) || (h->dynindx & 0xffff8000))
+         bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
+       else
+         bfd_put_32 (output_bfd,
+                     STUB_LI16S (output_bfd, h->dynindx & 0xffff), stub + idx);
+         
        BFD_ASSERT (h->plt.offset <= s->size);
!       memcpy (s->contents + h->plt.offset,
!               stub, MIPS_FUNCTION_STUB_SIZE (info));
  
        /* Mark the symbol as undefined.  plt.offset != -1 occurs
  	 only for the referenced symbol.  */
*************** _bfd_mips_elf_finish_dynamic_sections (b
*** 8827,8836 ****
  	      {
  		file_ptr dummy_offset;
  
! 		BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE);
! 		dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE;
  		memset (s->contents + dummy_offset, 0,
! 			MIPS_FUNCTION_STUB_SIZE);
  	      }
  	  }
        }
--- 8858,8867 ----
  	      {
  		file_ptr dummy_offset;
  
! 		BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE (info));
! 		dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE (info);
  		memset (s->contents + dummy_offset, 0,
! 			MIPS_FUNCTION_STUB_SIZE (info));
  	      }
  	  }
        }

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2006-06-11 20:03 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-08 23:03 [PATCH] (version 2) Change MIPS linker stubs to allow for more than 2^15 symbols David Daney
2006-06-08 23:12 ` Thiemo Seufer
2006-06-08 23:19   ` David Daney
2006-06-09  1:16     ` Thiemo Seufer
2006-06-09  0:01   ` David Daney
2006-06-09  6:38     ` David Daney
2006-06-08 23:35 ` Daniel Jacobowitz
2006-06-09  7:59 ` Richard Sandiford
2006-06-09 16:39   ` Thiemo Seufer
2006-06-09 18:18     ` David Daney
2006-06-09 18:23       ` Thiemo Seufer
2006-06-09 19:40         ` David Daney
2006-06-09 18:28     ` Daniel Jacobowitz
2006-06-09 19:24       ` David Daney
2006-06-09 19:27         ` Paul Koning
2006-06-09 21:00     ` Richard Sandiford
2006-06-10 16:04       ` Richard Sandiford
2006-06-11  0:07         ` Eric Christopher
2006-06-11  0:13         ` Thiemo Seufer
2006-06-11  0:26           ` Daniel Jacobowitz
2006-06-11  0:42           ` Eric Christopher
2006-06-11  8:21             ` Thiemo Seufer
2006-06-11  8:41               ` Richard Sandiford
2006-06-11 15:46                 ` David Daney
2006-06-11 13:27           ` Richard Sandiford
2006-06-11 19:29             ` Thiemo Seufer
2006-06-11 20:03               ` Richard Sandiford
2006-06-11 20:42                 ` Thiemo Seufer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).