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]

Re: [PATCH] (version 2) Change MIPS linker stubs to allow for more than 2^15 symbols.


Richard Sandiford wrote:
[snip]
> I've attached two patches.  The first is relative to Thiemo's patch
> from yesterday; the second is a complete patch against mainline.
> 
> Tested on mipsel-linux-gnu, mips64-linux-gnu and mipsisa64-elf.
> OK to install?
> 
> bfd/
> 	* elfxx-mips.c (mips_elf_link_hash_table): Add function_stub_size.
> 	(STUB_ORI): New macro.
> 	(STUB_LI16U): Fix formatting.
> 	(MIPS_FUNCTION_STUB_SIZE): Delete.
> 	(MIPS_FUNCTION_STUB_MAX_SIZE): Likewise.
> 	(MIPS_FUNCTION_STUB_NORMAL_SIZE): New macro.
> 	(MIPS_FUNCTION_STUB_BIG_SIZE): Likewise.
> 	(_bfd_mips_elf_adjust_dynamic_symbol): Use htab->function_stub_size
> 	instead of MIPS_FUNCTION_STUB_SIZE.
> 	(count_section_dynsyms): New function, split out from
> 	_bfd_mips_elf_final_link.
> 	(_bfd_mips_elf_always_size_sections): Get a worst-case estimate
> 	of the number of dynamic symbols needed and use it to set up
> 	function_stub_size.  Use function_stub_size rather than
> 	MIPS_FUNCTION_STUB_SIZE to determine the size of the stub section.
> 	Use 16-byte stubs for 0x10000 dynamic symbols.
> 	(_bfd_mips_elf_size_dynamic_sections): Use htab->function_stub_size
> 	instead of MIPS_FUNCTION_STUB_SIZE.  Fix formatting.
> 	(_bfd_mips_elf_finish_dynamic_symbol): Likewise.  Change the
> 	size of the stub buffer from MIPS_FUNCTION_STUB_MAX_SIZE to
> 	MIPS_FUNCTION_STUB_BIG_SIZE.  Tweak the check for unhandled dynindxes.
> 	Use MIPS_FUNCTION_STUB_BIG_SIZE rather than a hard-coded 20.
> 	Use STUB_ORI rather than STUB_LI16U for big stubs.
> 	(_bfd_mips_elf_link_hash_table_create): Initialize function_stub_size.
> 	(_bfd_mips_elf_final_link): Use count_section_dynsyms.
> 
> ld/testsuite/
> 	* ld-mips-elf/stub-dynsym-1.s,
> 	* ld-mips-elf/stub-dynsym-1.ld,
> 	* ld-mips-elf/stub-dynsym-1-7fff.d,
> 	* ld-mips-elf/stub-dynsym-1-8000.d,
> 	* ld-mips-elf/stub-dynsym-1-fff0.d,
> 	* ld-mips-elf/stub-dynsym-1-10000.d,
> 	* ld-mips-elf/stub-dynsym-1-2fe80.d: New test.
> 	* ld-mips-elf/mips-elf.exp: Run it.
> 

Ok.

I felt the urge to do some more cleanups (interdiff appended),
the only function change was to add the IRIX dummy entry to the
worst case calculation.

Don't let this one stop you to apply your patch. :-)


Thiemo


diff -u bfd/elfxx-mips.c bfd/elfxx-mips.c
--- bfd/elfxx-mips.c	10 Jun 2006 10:16:53 -0000
+++ bfd/elfxx-mips.c	10 Jun 2006 23:56:56 -0000
@@ -624,24 +624,7 @@
    offsets from $gp.  */
 #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_ORI(VAL) (0x37180000 + (VAL))	/* ori t8,t8,VAL */
-#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 */
-
+/* Function stub sizes as created by mips_elf_build_function_stub.  */
 #define MIPS_FUNCTION_STUB_NORMAL_SIZE 16
 #define MIPS_FUNCTION_STUB_BIG_SIZE 20
 
@@ -7180,9 +7163,10 @@
   /* Get a worst-case estimate of the number of dynamic symbols needed.
      At this point, dynsymcount does not account for section symbols
      and count_section_dynsyms may overestimate the number that will
-     be needed.  */
+     be needed.  Also account for the IRIX dummy entry.  */
   dynsymcount = (elf_hash_table (info)->dynsymcount
-		 + count_section_dynsyms (output_bfd, info));
+		 + count_section_dynsyms (output_bfd, info)
+		 + 1);
 
   /* Determine the size of one stub entry.  */
   htab->function_stub_size = (dynsymcount > 0x10000
@@ -8034,6 +8018,66 @@
 	}
 }
 
+static bfd_boolean
+mips_elf_build_function_stub (bfd *output_bfd, struct bfd_link_info *info,
+			      struct elf_link_hash_entry *h, asection *s)
+{
+  bfd_byte *stub;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  stub = s->contents + h->plt.offset;
+
+  BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
+              || (h->dynindx <= 0xffff));
+
+  /* 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 & ~0x7fffffff)
+	return FALSE;
+
+  /* Fill the stub.  */
+  bfd_put_32 (output_bfd, (ABI_64_P (output_bfd)
+			   ? 0xdf998010		/* ld t9, 0x8010(gp) */
+			   : 0x8f998010),	/* lw t9, 0x8010(gp) */
+	      stub);
+  bfd_put_32 (output_bfd, (ABI_64_P (output_bfd)
+			   ? 0x03e0782d		/* daddu t7, ra */
+			   : 0x03e07821),	/* addu t7, ra */
+	      stub += 4);
+  if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
+    {
+      /* lui t8, %hi(DYNINDX) */
+      bfd_put_32 (output_bfd, 0x3c180000 | ((h->dynindx >> 16) & 0x7fff),
+		  stub += 4);
+    }
+  bfd_put_32 (output_bfd, 0x0320f809, stub += 4); /* jalr t9, ra */
+  /* If a large stub is not required and sign extension is not a problem,
+     then use legacy code in the stub.  */
+  if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
+    {
+      /* ori t8, t8, %lo(DYNINDX) # unsigned */
+      bfd_put_32 (output_bfd, 0x37180000 | (h->dynindx & 0xffff), stub += 4);
+    }
+  else if (h->dynindx & ~0x7fff)
+    {
+      /* ori t8, zero, %lo(DYNINDX) # unsigned */
+      bfd_put_32 (output_bfd, 0x34180000 | (h->dynindx & 0xffff), stub += 4);
+    }
+  else
+    {
+      bfd_put_32 (output_bfd, (ABI_64_P (output_bfd)
+			       /* daddiu t8, zero, %lo(DYNINDX) # signed */
+			       ? (0x64180000 + h->dynindx)
+			       /* addiu t8, zero, %lo(DYNINDX) # signed */
+			       : (0x24180000 + h->dynindx)), stub += 4);
+    }
+
+  BFD_ASSERT (h->plt.offset <= s->size);
+  return TRUE;
+}
+
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
@@ -8047,7 +8091,6 @@
   asection *sgot;
   struct mips_got_info *g, *gg;
   const char *name;
-  int idx;
   struct mips_elf_link_hash_table *htab;
 
   htab = mips_elf_hash_table (info);
@@ -8056,7 +8099,6 @@
   if (h->plt.offset != MINUS_ONE)
     {
       asection *s;
-      bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];
 
       /* This symbol has a stub.  Set it up.  */
 
@@ -8067,41 +8109,7 @@
       BFD_ASSERT (s != NULL);
 
-      BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
-                  || (h->dynindx <= 0xffff));
-
-      /* 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 & ~0x7fffffff)
+      if (!mips_elf_build_function_stub (output_bfd, info, h, s))
 	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 (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
-        {
-          bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16) & 0x7fff),
-                      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 (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
-	bfd_put_32 (output_bfd, STUB_ORI (h->dynindx & 0xffff), stub + idx);
-      else if (h->dynindx & ~0x7fff)
-        bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
-      else
-        bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
-		    stub + idx);
-
-      BFD_ASSERT (h->plt.offset <= s->size);
-      memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size);
-
       /* Mark the symbol as undefined.  plt.offset != -1 occurs
 	 only for the referenced symbol.  */
@@ -8114,8 +8122,7 @@
 		       + h->plt.offset);
     }
 
-  BFD_ASSERT (h->dynindx != -1
-	      || h->forced_local);
+  BFD_ASSERT (h->dynindx != -1 || h->forced_local);
 
   sgot = mips_elf_got_section (dynobj, FALSE);
   BFD_ASSERT (sgot != NULL);


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