Possible Relocation Overflow ??

Mark Mitchell mark@codesourcery.com
Tue Jul 13 15:28:00 GMT 1999


>>>>> "Ian" == Ian Lance Taylor <ian@zembu.com> writes:

    Ian>    Date: Tue, 13 Jul 1999 20:25:03 +0530 From: "Koundinya.K"
    Ian> <kk@ddeorg.soft.net>

    Ian>    /usr/cygnus/H-mips-dde-sysv4.2MP/lib/crt1.o: In function
    Ian> `__start':
    Ian> /usr/cygnus/H-mips-dde-sysv4.2MP/lib/crt1.o(.text+0x14):
    Ian> relocation truncated to fit: R_MIPS_LO16 _gp_disp

    Ian> Mark, your code does overflow checking on R_MIPS_LO16 applied
    Ian> to _gp_disp.  That is what the ABI recommends, but I don't
    Ian> see how it can possibly work.  Code routinely uses
    Ian> R_MIPS_HI16 and R_MIPS_LO16 to determine _gp_disp.  It's OK
    Ian> if the R_MIPS_LO16 overflows, because the R_MIPS_HI16 is
    Ian> there to take care of it.

    Ian>    /usr/cygnus/H-mips-dde-sysv4.2MP/lib/crti.o: In function
    Ian> `_init':
    Ian> /usr/cygnus/H-mips-dde-sysv4.2MP/lib/crti.o(.init+0xc):
    Ian> undefined reference to `_gp_disp'

    Ian> Mark, if you look back at the original code, you will see
    Ian> that the test for _gp_disp is done as the start of a series
    Ian> of if conditions.  Testing for an undefined symbol is only
    Ian> done if the symbol is not _gp_disp. 

I have attempted to restore the previous behavior with the following
patch, which I checked in.  (Of course, this still leaves the
R_MIPS16* issues to resolve.)

Also, since I didn't ever get a test-case, I didn't have a way of
making sure that this fixed the problem.

Ian, I would appreciate your inspection.

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

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

	* elf32-mips.c (mips_elf_calculate_relocation): Do not complain
	when _gp_disp is undefined.  Do not check R_MIPS_LO16 for overflow
	when the relocation is against _gp_disp.

Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.19
diff -u -p -r1.19 elf32-mips.c
--- elf32-mips.c	1999/07/12 17:15:34	1.19
+++ elf32-mips.c	1999/07/13 22:20:24
@@ -5770,11 +5770,13 @@ mips_elf_calculate_relocation (abfd, 
 
 	  gp_disp_p = true;
 	}
-
-      /* If this symbol is defined, calculate its address.  */
-      if ((h->root.root.type == bfd_link_hash_defined
-	   || h->root.root.type == bfd_link_hash_defweak)
-	  && h->root.root.u.def.section)
+      /* 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
+	 its defined.  */
+      else if ((h->root.root.type == bfd_link_hash_defined
+		|| h->root.root.type == bfd_link_hash_defweak)
+	       && h->root.root.u.def.section)
 	{
 	  sec = h->root.root.u.def.section;
 	  if (sec->output_section)
@@ -5908,7 +5910,22 @@ mips_elf_calculate_relocation (abfd, 
       else
 	{
 	  value = addend + gp - p + 4;
-	  overflowed_p = mips_elf_overflow_p (value, 16);
+	  /* The MIPS ABI requires checking the R_MIPS_LO16 relocation
+	     for overflow.  But, on, say, Irix 5, relocations against
+	     _gp_disp are normally generated from the .cpload
+	     pseudo-op.  It generates code that normally looks like
+	     this:
+
+	       lui    $gp,%hi(_gp_disp)
+	       addiu  $gp,$gp,%lo(_gp_disp)
+	       addu   $gp,$gp,$t9
+
+	     Here $t9 holds the address of the function being called,
+	     as required by the MIPS ELF ABI.  The R_MIPS_LO16
+	     relocation can easily overlfow in this situation, but the
+	     R_MIPS_HI16 relocation will handle the overflow.
+	     Therefore, we consider this a bug in the MIPS ABI, and do
+	     not check for overflow here.  */
 	}
       break;
 


More information about the Binutils mailing list