This is the mail archive of the binutils@sourceware.cygnus.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]

Re: PATCH for 64-bit MIPS ELF buglets



Ian --

  Here's a patch which attempts to restore the MIPS16 stub handling
stuff.  OK to check in?

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-07-15  Mark Mitchell  <mark@codesourcery.com>

	* elf32-mips.c (mips_elf_stub_section_p): New function.
	(mips_elf_calculate_relocation): Handle MIPS16 stub functions.
	(mips_elf_relocate_section): Adjust calling sequence for
	mips_elf_calculate_relocation and mips_elf_perform_relocation.
	(mips_elf_perform_relocation): Turn `jal' into `jalx' where
	required.

Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.26
diff -u -p -r1.26 elf32-mips.c
--- elf32-mips.c	1999/07/14 19:00:32	1.26
+++ elf32-mips.c	1999/07/15 17:29:25
@@ -168,13 +168,14 @@ static boolean mips_elf_next_lo16_addend
 static bfd_reloc_status_type mips_elf_calculate_relocation
   PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
 	   const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
-	   Elf_Internal_Sym *, asection **, bfd_vma *, const char **));
+	   Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
+	   boolean *));
 static bfd_vma mips_elf_obtain_contents
   PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
-static void mips_elf_perform_relocation
+static boolean mips_elf_perform_relocation
   PARAMS ((struct bfd_link_info *, reloc_howto_type *, 
 	   const Elf_Internal_Rela *, bfd_vma,
-	   bfd *, bfd_byte *));
+	   bfd *, asection *, bfd_byte *, boolean));
 static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *));
 static boolean mips_elf_sort_hash_table_f 
   PARAMS ((struct mips_elf_link_hash_entry *, PTR));
@@ -192,6 +193,8 @@ static unsigned int mips_elf_create_dyna
 	   long, bfd_vma, asection *));
 static void mips_elf_allocate_dynamic_relocations 
   PARAMS ((bfd *, unsigned int));
+static boolean mips_elf_stub_section_p 
+  PARAMS ((bfd *, asection *));
 
 /* The level of IRIX compatibility we're striving for.  */
 
@@ -5662,6 +5665,8 @@ mips_elf_create_dynamic_relocation (outp
    RELOCATION; RELOCATION->R_ADDEND is ignored.
 
    The result of the relocation calculation is stored in VALUEP.
+   REQUIRE_JALXP indicates whether or not the opcode used with this
+   relocation must be JALX.
 
    This function returns bfd_reloc_continue if the caller need take no
    further action regarding this relocation, bfd_reloc_notsupported if
@@ -5679,7 +5684,8 @@ mips_elf_calculate_relocation (abfd, 
 			       local_syms,
 			       local_sections,
 			       valuep,
-			       namep) 
+			       namep,
+			       require_jalxp) 
      bfd *abfd;
      bfd *input_bfd;
      asection *input_section;
@@ -5691,6 +5697,7 @@ mips_elf_calculate_relocation (abfd, 
      asection **local_sections;
      bfd_vma *valuep;
      const char **namep;
+     boolean *require_jalxp;
 {
   /* The eventual value we will return.  */
   bfd_vma value;
@@ -5822,7 +5827,65 @@ mips_elf_calculate_relocation (abfd, 
 	  return bfd_reloc_undefined;
 	}
     }
+  
+  /* If this is a 32-bit call to a 16-bit function, we need to
+     redirect the call to the stub, unless we're already *in* a stub.  */
+  if (r_type != R_MIPS16_26 && !info->relocateable
+      && ((h != NULL && h->fn_stub != NULL)
+	  || (local_p && elf_tdata (input_bfd)->local_stubs != NULL
+	      && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
+      && !mips_elf_stub_section_p (input_bfd, input_section))
+    {
+      /* This is a 32-bit call to a 16-bit function.  We should
+	 have already noticed that we were going to need the
+	 stub.  */
+      if (local_p)
+	sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
+      else
+	{
+	  BFD_ASSERT (h->need_fn_stub);
+	  sec = h->fn_stub;
+	}
 
+      symbol = sec->output_section->vma + sec->output_offset;
+      *require_jalxp = true;
+    }
+  /* If this is a 16-bit call to a 32-bit function, we need to
+     redirect the call to the stub.  */
+  else if (r_type == R_MIPS16_26 && !info->relocateable
+	   && h != NULL 
+	   && (h->call_stub != NULL || h->call_fp_stub != NULL)
+	   && h->root.other != STO_MIPS16)
+    {
+      /* If both call_stub and call_fp_stub are defined, we can figure
+	 out which one to use by seeing which one appears in the input
+	 file.  */
+      if (h->call_stub != NULL && h->call_fp_stub != NULL)
+	{
+	  asection *o;
+
+	  for (o = input_bfd->sections; o != NULL; o = o->next)
+	    {
+	      if (strncmp (bfd_get_section_name (input_bfd, o),
+			   CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0)
+		{
+		  sec = h->call_fp_stub;
+		  break;
+		}
+	    }
+	  if (sec == NULL)
+	    sec = h->call_stub;
+	}
+      else if (h->call_stub != NULL)
+	sec = h->call_stub;
+      else
+	sec = h->call_fp_stub;
+
+      BFD_ASSERT (sec->_raw_size > 0);
+      symbol = sec->output_section->vma + sec->output_offset;
+      *require_jalxp = true;
+    }
+
   /* If we haven't already determined the GOT offset, or the GP value,
      and we're going to need it, get it now.  */
   switch (r_type)
@@ -6114,19 +6177,24 @@ mips_elf_obtain_contents (howto, relocat
 /* It has been determined that the result of the RELOCATION is the
    VALUE.  Use HOWTO to place VALUE into the output file at the
    appropriate position.  The SECTION is the section to which the
-   relocatin applies.
+   relocatin applies.  If REQUIRE_JALX is true, then the opcode used
+   for the relocation must be either JAL or JALX, and it is
+   unconditionally converted to JALX.
 
    Returns false if anything goes wrong.  */
 
-static void
+static boolean
 mips_elf_perform_relocation (info, howto, relocation, value,
-			     input_bfd, contents)
+			     input_bfd, input_section, 
+			     contents, require_jalx)
      struct bfd_link_info *info;
      reloc_howto_type *howto;
      const Elf_Internal_Rela *relocation;
      bfd_vma value;
      bfd *input_bfd;
+     asection *input_section;
      bfd_byte *contents;
+     boolean require_jalx;
 {
   bfd_vma x;
   bfd_byte *location;
@@ -6239,6 +6307,24 @@ mips_elf_perform_relocation (info, howto
   /* Set the field.  */
   x |= (value & howto->dst_mask);
 
+  if (require_jalx)
+    {
+      /* If the opcode is not JAL or JALX, there's a problem.  */
+      if ((x & 0xf8000000) != 0x18000000)
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: %s+0x%lx: jump to stub routine which is not jal"),
+	     bfd_get_filename (input_bfd),
+	     input_section->name,
+	     (unsigned long) relocation->r_offset);
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+
+      /* Make this the JALX opcode.  */
+      x = (x & ~0xfc000000) | 0x1c000000;
+    }
+
   /* Swap the high- and low-order 16 bits on little-endian systems
      when doing a MIPS16 relocation.  */
   if ((ELF32_R_TYPE (relocation->r_info) == R_MIPS16_GPREL
@@ -6248,6 +6334,21 @@ mips_elf_perform_relocation (info, howto
   
   /* Put the value into the output.  */
   bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
+  return true;
+}
+
+/* Returns true if SECTION is a MIPS16 stub section.  */
+
+static boolean
+mips_elf_stub_section_p (abfd, section)
+     bfd *abfd;
+     asection *section;
+{
+  const char *name = bfd_get_section_name (abfd, section);
+
+  return (strncmp (name, FN_STUB, sizeof FN_STUB - 1) == 0
+	  || strncmp (name, CALL_STUB, sizeof CALL_STUB - 1) == 0
+	  || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0);
 }
 
 /* Relocate a MIPS ELF section.  */
@@ -6279,6 +6380,7 @@ _bfd_mips_elf_relocate_section (output_b
       const char *name;
       bfd_vma value;
       reloc_howto_type *howto;
+      boolean require_jalx;
 
       /* Find the relocation howto for this relocation.  */
       if (ELF32_R_TYPE (rel->r_info) == R_MIPS_64
@@ -6383,7 +6485,8 @@ _bfd_mips_elf_relocate_section (output_b
 					     local_syms,
 					     local_sections,
 					     &value,
-					     &name))
+					     &name,
+					     &require_jalx))
 	{
 	case bfd_reloc_continue:
 	  /* There's nothing to do.  */
@@ -6476,8 +6579,10 @@ _bfd_mips_elf_relocate_section (output_b
 	}
 
       /* Actually perform the relocation.  */
-      mips_elf_perform_relocation (info, howto, rel, value, input_bfd, 
-				   contents);
+      if (!mips_elf_perform_relocation (info, howto, rel, value, input_bfd, 
+					input_section, contents,
+					require_jalx))
+	return false;
     }
 
   return true;

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