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]

RFC: Patch to fix MIPS -mno-shared with multi-got...


This patch added by Ian Lance Taylor:

http://sourceware.org/ml/binutils/2004-12/msg00094.html

Added a new option for the MIPS assembler -mno-shared which as he stated in the message referenced above:


-------------8<----------------- This patch adds a new option to the MIPS assembler: -mno-shared. Normally the .cpload pseudo-op generates code which looks like this:

	lui	$gp,%hi(_gp_disp)
	addiu	$gp,$gp,%lo(_gp_disp)
	addu	$gp,$gp,.cpload argument

With -mno-shared, the .cpload pseudo-op will generate code that looks
like this:

	lui	$gp,%hi(_gp)
	addiu	$gp,$gp,%lo(_gp)
------------8<-------------------


When doing a multi-got link the "_gp_disp" virtual symbol refers to one of the several GOTs in the output.


The problem is that "_gp" points to the primary GOT but the relocations need to be done against which ever GOT is used by the module being linked

The attached patch adds special handling for "_gp" so that it is treated in a manner similar to "_gp_disp"

It allows my large (multi-got) application to be compiled with -Wa,-mno-shared which is good.

One thing I am not sure about is if there is existing code somewhere that that will break with the patch.

Possible problems are code that use relocations other than R_MIPS_HI16, R_MIPS_LO16, R_MIPS16_HI16 and R_MIPS16_LO16 against "_gp" as they would now be illegal. Also multi-got code that for some reason needed to refer to the "real _gp" instead of the GOT corresponding to the module.

Thoughts?

If it is thought to be a good patch, I could probably create some test cases for it.

David Daney

--- /home/daney/binutils-050218/bfd/elfxx-mips.c	2005-02-15 20:45:23.000000000 -0800
+++ bfd/elfxx-mips.c	2005-03-03 12:19:30.000000000 -0800
@@ -3039,6 +3039,8 @@ mips_elf_calculate_relocation (bfd *abfd
   bfd_boolean local_p, was_local_p;
   /* TRUE if the symbol referred to by this relocation is "_gp_disp".  */
   bfd_boolean gp_disp_p = FALSE;
+  /* TRUE if the symbol referred to by this relocation is "_gp".  */
+  bfd_boolean gp_p = FALSE;
   Elf_Internal_Shdr *symtab_hdr;
   size_t extsymoff;
   unsigned long r_symndx;
@@ -3135,6 +3137,20 @@ mips_elf_calculate_relocation (bfd *abfd
 
 	  gp_disp_p = TRUE;
 	}
+      /* See if this is the special _gp symbol.  Note that such a
+	 symbol must always be a global symbol.  */
+      else if (strcmp (*namep, "_gp") == 0
+	  && ! NEWABI_P (input_bfd))
+	{
+	  /* Relocations against _gp are permitted only with
+	     R_MIPS_HI16 and R_MIPS_LO16 relocations.  */
+	  if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16
+	      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+	    return bfd_reloc_notsupported;
+
+	  gp_p = TRUE;
+	}
+
       /* If this symbol is defined, calculate its address.  Note that
 	 _gp_disp is a magic symbol, always implicitly defined by the
 	 linker, so it's inappropriate to check to see whether or not
@@ -3415,12 +3431,7 @@ mips_elf_calculate_relocation (bfd *abfd
 
     case R_MIPS_HI16:
     case R_MIPS16_HI16:
-      if (!gp_disp_p)
-	{
-	  value = mips_elf_high (addend + symbol);
-	  value &= howto->dst_mask;
-	}
-      else
+      if (gp_disp_p)
 	{
 	  /* For MIPS16 ABI code we generate this sequence
 	        0: li      $v0,%hi(_gp_disp)
@@ -3437,13 +3448,21 @@ mips_elf_calculate_relocation (bfd *abfd
 	    value = mips_elf_high (addend + gp - p);
 	  overflowed_p = mips_elf_overflow_p (value, 16);
 	}
+      else if (gp_p)
+        {
+	  value = mips_elf_high (addend + gp);
+	  overflowed_p = mips_elf_overflow_p (value, 16);
+        }
+      else
+	{
+	  value = mips_elf_high (addend + symbol);
+	  value &= howto->dst_mask;
+	}
       break;
 
     case R_MIPS_LO16:
     case R_MIPS16_LO16:
-      if (!gp_disp_p)
-	value = (symbol + addend) & howto->dst_mask;
-      else
+      if (gp_disp_p)
 	{
 	  /* See the comment for R_MIPS16_HI16 above for the reason
 	     for this conditional.  */
@@ -3468,6 +3487,12 @@ mips_elf_calculate_relocation (bfd *abfd
 	     Therefore, we consider this a bug in the MIPS ABI, and do
 	     not check for overflow here.  */
 	}
+      else if (gp_p)
+        {
+          value = addend + gp;
+        }
+      else
+	value = (symbol + addend) & howto->dst_mask;
       break;
 
     case R_MIPS_LITERAL:

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