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: MIPS ELF embedded-pic support.


> Date: 15 Oct 1999 13:31:23 -0400
> From: Ian Lance Taylor <ian@zembu.com>
> CC: binutils@sourceware.cygnus.com, rth@cygnus.com
> 
>    Date: Fri, 15 Oct 1999 16:08:18 +1000
>    From: Geoff Keating <geoffk@ozemail.com.au>
> 
>    I've tested this pretty extensively, including the gcc testsuite, on
>    both mips32 (actually mipstx39), and mips64.  I haven't checked to see
>    if the old COFF support is still working, although I did try
>    not to break it.

Here's a revised patch.

> Is this wise?  If the ELF linker will ever perform this optimization,
> which as I recall is required to support embedded PIC for large
> programs, then old object files may break.  I would recommend against
> checking bfd_target_elf_flavour in this context.

Done.

>    @@ -9470,29 +9476,28 @@ md_apply_fix (fixP, valueP)
> 	 symbol, we need to adjust the value.  */
>     #ifdef OBJ_ELF
...
> I'm not comfortable with these changes.  You appear to be changing the
> behaviour for STO_MIPS16, S_IS_WEAK, and linkonce symbols, and perhaps
> others.  Is that wise?  Have you tested those cases thoroughly?

I've run the g++ test suite, which will check the weak and linkonce
cases; nothing terrible happened.

If someone could write a test case for STO_MIPS16 (and it didn't
work), I could fix it.  I expect, though, that you'd fix it somewhere
else than in this code; it's easier to have 'value' have some
consistent meaning after this code (although it doesn't before it),
and then use that in subsequent processing.

> You can not apply logic to this code.  The whole gas relocation system
> is completely and horribly broken, as discussed in the internal
> documentation.  I get scared by any change to this code.

Yes.  That's why testcases are so important.  It's just a pity that
MIPS gas didn't have any before I started.

Note that in this version of the patch I added a comment explaining
this; and I also had to change the test from 
+      if (fixP->fx_pcrel)
to
+      if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
which I consider an excellent example of the behaviour you mention.
On the bright side, I've learnt how to make GAS pass md_apply_fix a
reloc, which can only be pc-relative, with fx_pcrel clear:  use local
labels.  I've added an example to the empic testcase.

I find it helps if fx_addnumber is always set to the ELF addend, this
simplifies later processing and makes debugging the code slightly
easier.  This accounts for some of the 'you appear to be changing'
behaviour you mention.

>    +	run_dump_test "empic"
...
> Can you make a version of this test which works for both ECOFF and
> ELF?

Unfortunately, I don't know anything about COFF so I would have no
idea whether or not the testcase was correct.

>    +++ binutils/include/elf/mips.h	Fri Oct 15 15:42:53 1999
...
> I think it's a bit nicer if the relocations are sorted in numeric
> order.

Done.

-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~/patches/cygnus/tx49-bin-empic-2.patch=============
md5sum: b231a7564a3a0c34 bc8d7230dbaf4dab 198443
Index: binutils/bfd/ChangeLog
0a
Thu Oct 14 16:39:00 1999  Geoffrey Keating  <geoffk@cygnus.com>

	* elf32-mips.c (mips_elf_next_relocation): Rename from
	mips_elf_next_lo16_relocation, and generalize to look
	for any relocation type.
	(elf_mips_howto_table): Make R_MIPS_PC16 pcrel_offset.
	(elf_mips_gnu_rel_hi16): Howto for R_MIPS_GNU_REL_HI16.
	(elf_mips_gnu_rel_lo16): Howto for R_MIPS_GNU_REL_LO16.
	(elf_mips_gnu_rel16_s2): Howto for R_MIPS_GNU_REL16_S2.
	(elf_mips_gnu_pcrel64): Howto for R_MIPS_PC64.
	(elf_mips_gnu_pcrel32): Howto for R_MIPS_PC32.
	(bfd_elf32_bfd_reloc_type_lookup): Add new relocs.
	(mips_rtype_to_howto): Likewise.
	(mips_elf_calculate_relocation): Handle new relocs.
	(_bfd_mips_elf_relocate_section): REL_HI16/REL_LO16 relocs
	are paired.  The addend for R_MIPS_GNU_REL16_S2
	is shifted right two bits.

.
md5sum: 5bf40784b402a958 3d74b5f1541812d7 167932
Index: binutils/gas/ChangeLog
0a
Fri Oct 15 14:55:23 1999  Geoffrey Keating  <geoffk@cygnus.com>

	* config/tc-mips.c (mips_ip): Don't put stuff in .rodata
	when embedded-pic.

	* config/tc-mips.c (SWITCH_TABLE): The ELF embedded-pic
 	implementation doesn't have special handling for switch
 	statements.
	(macro_build): Allow for code in sections other than .text.
	(macro): Likewise.
	(mips_ip): Likewise.
	(md_apply_fix): Do pc-relative relocation madness for MIPS ELF.
  	Don't perform relocs if we will be outputting them.
	(tc_gen_reloc): For ELF, just use fx_addnumber for pc-relative
 	relocations.  Allow BFD_RELOC_16_PCREL_S2 relocs when
 	embedded-pic.

.
md5sum: 3c22ee39249e91c9 440aa7f91caf17b2 84686
Index: binutils/gas/testsuite/ChangeLog
0a
Thu Oct 14 16:38:18 1999  Geoffrey Keating  <geoffk@cygnus.com>

	* gas/mips/empic.d: New file.
	* gas/mips/empic.s: New file.
	* gas/mips/mips.exp: Add empic.

.
md5sum: e04339d228b6d4d8 db4a37ff901fe319 24093
Index: binutils/include/elf/ChangeLog
0a
1999-09-19  Geoffrey Keating  <geoffk@cygnus.com>

	* mips.h: Add R_MIPS_GNU_REL_HI16, R_MIPS_GNU_REL_LO16,
 	R_MIPS_GNU_REL16_S2, R_MIPS_PC64 and R_MIPS_PC32 relocation
 	numbers.

.
Changed files:
binutils/bfd/ChangeLog
binutils/gas/ChangeLog
binutils/gas/testsuite/ChangeLog
binutils/include/elf/ChangeLog
binutils/bfd/elf32-mips.c
binutils/gas/config/tc-mips.c
binutils/gas/testsuite/gas/mips/mips.exp
binutils/gas/testsuite/gas/mips/empic.s
binutils/gas/testsuite/gas/mips/empic.d
binutils/include/elf/mips.h
md5sum: 0cc7822e898c842b 5fa4dd2cbbb6bcac 265210
--- /sloth/disk0/co/binutils-mainline/binutils/bfd/elf32-mips.c	Fri Oct  8 13:03:28 1999
+++ binutils/bfd/elf32-mips.c	Sat Oct 30 17:02:43 1999
@@ -157,8 +157,9 @@ static boolean mips_elf_record_global_go
 	   struct mips_got_info *));
 static bfd_vma mips_elf_got_page
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static const Elf_Internal_Rela *mips_elf_next_lo16_relocation
-  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *));
+static const Elf_Internal_Rela *mips_elf_next_relocation
+  PARAMS ((unsigned int, const Elf_Internal_Rela *, 
+	   const Elf_Internal_Rela *));
 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 *,
@@ -612,7 +613,7 @@ static reloc_howto_type elf_mips_howto_t
 	 true,			/* partial_inplace */
 	 0xffff,		/* src_mask */
 	 0xffff,		/* dst_mask */
-	 false),		/* pcrel_offset */
+	 true),			/* pcrel_offset */
 
   /* 16 bit call through global offset table.  */
   HOWTO (R_MIPS_CALL16,		/* type */
@@ -942,6 +943,87 @@ static reloc_howto_type elf_mips16_gprel
 	 false);		/* pcrel_offset */
 
 
+/* GNU extensions for embedded-pic.  */
+/* High 16 bits of symbol value, pc-relative.  */
+static reloc_howto_type elf_mips_gnu_rel_hi16 =
+  HOWTO (R_MIPS_GNU_REL_HI16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_hi16_reloc,	/* special_function */
+	 "R_MIPS_GNU_REL_HI16",	/* name */
+	 true,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
+/* Low 16 bits of symbol value, pc-relative.  */
+static reloc_howto_type elf_mips_gnu_rel_lo16 =
+  HOWTO (R_MIPS_GNU_REL_LO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_lo16_reloc,	/* special_function */
+	 "R_MIPS_GNU_REL_LO16",	/* name */
+	 true,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
+/* 16 bit offset for pc-relative branches.  */
+static reloc_howto_type elf_mips_gnu_rel16_s2 =
+  HOWTO (R_MIPS_GNU_REL16_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_MIPS_GNU_REL16_S2",	/* name */
+	 true,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
+/* 64 bit pc-relative.  */
+static reloc_howto_type elf_mips_gnu_pcrel64 =
+  HOWTO (R_MIPS_PC64,		/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_MIPS_PC64",		/* name */
+	 true,			/* partial_inplace */
+	 MINUS_ONE,		/* src_mask */
+	 MINUS_ONE,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
+/* 32 bit pc-relative.  */
+static reloc_howto_type elf_mips_gnu_pcrel32 =
+  HOWTO (R_MIPS_PC32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_MIPS_PC32",		/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
 /* GNU extension to record C++ vtable hierarchy */
 static reloc_howto_type elf_mips_gnu_vtinherit_howto =
   HOWTO (R_MIPS_GNU_VTINHERIT,	/* type */
@@ -1880,6 +1962,16 @@ static reloc_howto_type *
       return &elf_mips_gnu_vtinherit_howto;
     case BFD_RELOC_VTABLE_ENTRY:
       return &elf_mips_gnu_vtentry_howto;
+    case BFD_RELOC_PCREL_HI16_S:
+      return &elf_mips_gnu_rel_hi16;
+    case BFD_RELOC_PCREL_LO16:
+      return &elf_mips_gnu_rel_lo16;
+    case BFD_RELOC_16_PCREL_S2:
+      return &elf_mips_gnu_rel16_s2;
+    case BFD_RELOC_64_PCREL:
+      return &elf_mips_gnu_pcrel64;
+    case BFD_RELOC_32_PCREL:
+      return &elf_mips_gnu_pcrel32;
     }
 }
 
@@ -1903,6 +1995,21 @@ mips_rtype_to_howto (r_type)
     case R_MIPS_GNU_VTENTRY:
       return &elf_mips_gnu_vtentry_howto;
       break;
+    case R_MIPS_GNU_REL_HI16:
+      return &elf_mips_gnu_rel_hi16;
+      break;
+    case R_MIPS_GNU_REL_LO16:
+      return &elf_mips_gnu_rel_lo16;
+      break;
+    case R_MIPS_GNU_REL16_S2:
+      return &elf_mips_gnu_rel16_s2;
+      break;
+    case R_MIPS_PC64:
+      return &elf_mips_gnu_pcrel64;
+      break;
+    case R_MIPS_PC32:
+      return &elf_mips_gnu_pcrel32;
+      break;
 
     default:
       BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
@@ -5442,11 +5549,12 @@ static bfd_vma
   return index;
 }
 
-/* Returns the first R_MIPS_LO16 relocation found, beginning with
+/* Returns the first relocation of type r_type found, beginning with
    RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
 
 static const Elf_Internal_Rela *
-mips_elf_next_lo16_relocation (relocation, relend)
+mips_elf_next_relocation (r_type, relocation, relend)
+     unsigned int r_type;
      const Elf_Internal_Rela *relocation;
      const Elf_Internal_Rela *relend;
 {
@@ -5458,7 +5566,7 @@ static const Elf_Internal_Rela *
      extension in general, as that is useful for GCC.  */
   while (relocation < relend)
     {
-      if (ELF32_R_TYPE (relocation->r_info) == R_MIPS_LO16)
+      if (ELF32_R_TYPE (relocation->r_info) == r_type)
 	return relocation;
 
       ++relocation;
@@ -6002,6 +6110,24 @@ mips_elf_calculate_relocation (abfd, 
       value &= howto->dst_mask;
       break;
 
+    case R_MIPS_PC32:
+    case R_MIPS_PC64:
+    case R_MIPS_GNU_REL_LO16:
+      value = symbol + addend - p;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_GNU_REL16_S2:
+      value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+      overflowed_p = mips_elf_overflow_p (value, 18);
+      value = (value >> 2) & howto->dst_mask;
+      break;
+
+    case R_MIPS_GNU_REL_HI16:
+      value = mips_elf_high (addend + symbol - p);
+      value &= howto->dst_mask;
+      break;
+
     case R_MIPS16_26:
       /* The calculation for R_MIPS_26 is just the same as for an
 	 R_MIPS_26.  It's only the storage of the relocated field into
@@ -6479,6 +6605,7 @@ _bfd_mips_elf_relocate_section (output_b
 		 combination of the addend stored in two different
 		 relocations.   */
 	      if (r_type == R_MIPS_HI16
+		  || r_type == R_MIPS_GNU_REL_HI16
 		  || (r_type == R_MIPS_GOT16
 		      && mips_elf_local_relocation_p (input_bfd, rel,
 						      local_sections)))
@@ -6486,6 +6613,7 @@ _bfd_mips_elf_relocate_section (output_b
 		  bfd_vma l;
 		  const Elf_Internal_Rela *lo16_relocation;
 		  reloc_howto_type *lo16_howto;
+		  int lo;
 
 		  /* The combined value is the sum of the HI16 addend,
 		     left-shifted by sixteen bits, and the LO16
@@ -6493,15 +6621,18 @@ _bfd_mips_elf_relocate_section (output_b
 		     a `lui' of the HI16 value, and then an `addiu' of
 		     the LO16 value.)  
 
-		     Scan ahead to find a matching R_MIPS_LO16
-		     relocation.  */
+		     Scan ahead to find a matching LO16 relocation.  */
+		  if (r_type == R_MIPS_GNU_REL_HI16)
+		    lo = R_MIPS_GNU_REL_LO16;
+		  else
+		    lo = R_MIPS_LO16;
 		  lo16_relocation 
-		    = mips_elf_next_lo16_relocation (rel, relend); 
+		    = mips_elf_next_relocation (lo, rel, relend); 
 		  if (lo16_relocation == NULL)
 		    return false;
 
 		  /* Obtain the addend kept there.  */
-		  lo16_howto = mips_rtype_to_howto (R_MIPS_LO16);
+		  lo16_howto = mips_rtype_to_howto (lo);
 		  l = mips_elf_obtain_contents (lo16_howto,
 						lo16_relocation,
 						input_bfd, contents);
@@ -6549,7 +6680,8 @@ _bfd_mips_elf_relocate_section (output_b
 	      || r_type == R_MIPS_LITERAL)
 	    addend -= (_bfd_get_gp_value (output_bfd)
 		       - _bfd_get_gp_value (input_bfd));
-	  else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
+	  else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26
+		   || r_type == R_MIPS_GNU_REL16_S2)
 	    /* The addend is stored without its two least
 	       significant bits (which are always zero.)  In a
 	       non-relocateable link, calculate_relocation will do
@@ -6565,17 +6697,19 @@ _bfd_mips_elf_relocate_section (output_b
 	  /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
 	     then we only want to write out the high-order 16 bits.
 	     The subsequent R_MIPS_LO16 will handle the low-order bits.  */
-	  if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16)
+	  if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
+	      || r_type == R_MIPS_GNU_REL_HI16)
 	    addend = mips_elf_high (addend);
 	  /* If the relocation is for an R_MIPS_26 relocation, then
 	     the two low-order bits are not stored in the object file;
 	     they are implicitly zero.  */
-	  else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
+	  else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26
+		   || r_type == R_MIPS_GNU_REL16_S2)
 	    addend >>= 2;
 
 	  if (rela_relocation_p)
 	    /* If this is a RELA relocation, just update the addend.
-               We have to cast away constness for REL.  */
+	       We have to cast away constness for REL.  */
 	    rel->r_addend = addend;
 	  else
 	    {
@@ -6626,7 +6760,7 @@ _bfd_mips_elf_relocate_section (output_b
 
 	case bfd_reloc_undefined:
 	  /* mips_elf_calculate_relocation already called the
-             undefined_symbol callback.  There's no real point in
+	     undefined_symbol callback.  There's no real point in
 	     trying to perform the relocation at this point, so we
 	     just skip ahead to the next relocation.  */
 	  continue;
md5sum: 5f829e51ef3ca104 76a282f145bf7329 336083
--- /sloth/disk0/co/binutils-mainline/binutils/gas/config/tc-mips.c	Wed Oct 27 14:30:00 1999
+++ binutils/gas/config/tc-mips.c	Sat Oct 30 17:04:53 1999
@@ -2564,7 +2564,6 @@ macro_build (place, counter, ep, name, f
 		  || r == BFD_RELOC_MIPS_GOT_LO16
 		  || r == BFD_RELOC_MIPS_CALL_LO16
 		  || (ep->X_op == O_subtract
-		      && now_seg == text_section
 		      && r == BFD_RELOC_PCREL_LO16));
 	  continue;
 
@@ -2578,7 +2577,6 @@ macro_build (place, counter, ep, name, f
 			      || r == BFD_RELOC_MIPS_GOT_HI16
 			      || r == BFD_RELOC_MIPS_CALL_HI16))
 		      || (ep->X_op == O_subtract
-			  && now_seg == text_section
 			  && r == BFD_RELOC_PCREL_HI16_S)));
 	  if (ep->X_op == O_constant)
 	    {
@@ -4117,23 +4115,23 @@ macro (ip)
       /* When generating embedded PIC code, we permit expressions of
 	 the form
 	   la	$4,foo-bar
-	 where bar is an address in the .text section.  These are used
+	 where bar is an address in the current section.  These are used
 	 when getting the addresses of functions.  We don't permit
 	 X_add_number to be non-zero, because if the symbol is
 	 external the relaxing code needs to know that any addend is
 	 purely the offset to X_op_symbol.  */
       if (mips_pic == EMBEDDED_PIC
 	  && offset_expr.X_op == O_subtract
-	  && now_seg == text_section
 	  && (symbol_constant_p (offset_expr.X_op_symbol)
-	      ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section
+	      ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
 	      : (symbol_equated_p (offset_expr.X_op_symbol)
 		 && (S_GET_SEGMENT
 		     (symbol_get_value_expression (offset_expr.X_op_symbol)
 		      ->X_add_symbol)
-		     == text_section)))
+		     == now_seg)))
 	  && breg == 0
-	  && offset_expr.X_add_number == 0)
+	  && (offset_expr.X_add_number == 0
+	      || OUTPUT_FLAVOR == bfd_target_elf_flavour))
 	{
 	  macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
 		       treg, (int) BFD_RELOC_PCREL_HI16_S);
@@ -7657,11 +7655,15 @@ mips_ip (str, ip)
 		      default: /* unused default case avoids warnings.  */
 		      case 'L':
 			newname = RDATA_SECTION_NAME;
-			if (USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
+			if ((USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
+			    || mips_pic == EMBEDDED_PIC)
 			  newname = ".lit8";
 			break;
 		      case 'F':
-			newname = RDATA_SECTION_NAME;
+			if (mips_pic == EMBEDDED_PIC)
+			  newname = ".lit8";
+			else
+			  newname = RDATA_SECTION_NAME;
 			break;
 		      case 'l':
 			assert (!USE_GLOBAL_POINTER_OPT
@@ -7804,9 +7806,8 @@ mips_ip (str, ip)
 		      || offset_expr.X_add_number < -0x8000)
 		  && (mips_pic != EMBEDDED_PIC
 		      || offset_expr.X_op != O_subtract
-		      || now_seg != text_section
 		      || (S_GET_SEGMENT (offset_expr.X_op_symbol)
-			  != text_section)))
+			  != now_seg)))
 		break;
 
 	      if (c == 'h' || c == 'H')
@@ -9447,6 +9448,7 @@ mips_frob_file ()
    fixup requires the special reloc.  */
 #define SWITCH_TABLE(fixp) \
   ((fixp)->fx_r_type == BFD_RELOC_32 \
+   && OUTPUT_FLAVOR != bfd_target_elf_flavour \
    && (fixp)->fx_addsy != NULL \
    && (fixp)->fx_subsy != NULL \
    && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
@@ -9494,28 +9496,32 @@ md_apply_fix (fixP, valueP)
      symbol, we need to adjust the value.  */
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
-    if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16 
-        || S_IS_WEAK (fixP->fx_addsy)
-        || (symbol_used_in_reloc_p (fixP->fx_addsy)
-            && (((bfd_get_section_flags (stdoutput,
-					 S_GET_SEGMENT (fixP->fx_addsy))
-		  & SEC_LINK_ONCE) != 0)
-		|| !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
-			     ".gnu.linkonce",
-			     sizeof (".gnu.linkonce") - 1))))
+    {
+      /* `*valuep' may contain the value of the symbol on which the reloc
+	 will be based; we have to remove it.  */
+      if (symbol_used_in_reloc_p (fixP->fx_addsy)
+	  && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
+	  && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
+	  && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
+	value -= S_GET_VALUE (fixP->fx_addsy);
 
-      {
-        value -= S_GET_VALUE (fixP->fx_addsy);
-        if (value != 0 && ! fixP->fx_pcrel)
-          {
-            /* In this case, the bfd_install_relocation routine will
-               incorrectly add the symbol value back in.  We just want
-               the addend to appear in the object file.  */
-            value -= S_GET_VALUE (fixP->fx_addsy);
-          }
-      }
-#endif
+      /* This code was generated using trial and error and so is
+	 fragile and not trustworthy.  If you change it, you should
+	 rerun the elf-rel, elf-rel2, and empic testcases and ensure
+	 they still pass.  */
+      if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
+	{
+	  value += fixP->fx_frag->fr_address + fixP->fx_where;
 
+	  /* BFD's REL handling, for MIPS, is _very_ weird.
+	     This gives the right results, but it can't possibly
+	     be the way things are supposed to work.  */
+	  if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
+	      || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
+	    value += fixP->fx_frag->fr_address + fixP->fx_where;
+	}
+    }
+#endif
 
   fixP->fx_addnumber = value;	/* Remember value for tc_gen_reloc */
 
@@ -9553,7 +9559,12 @@ md_apply_fix (fixP, valueP)
     case BFD_RELOC_PCREL_HI16_S:
       /* The addend for this is tricky if it is internal, so we just
 	 do everything here rather than in bfd_install_relocation.  */
-      if ((symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour 
+	  && !fixP->fx_done
+	  && value != 0)
+	break;
+      if (fixP->fx_addsy
+	  && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
 	{
 	  /* For an external symbol adjust by the address to make it
 	     pcrel_offset.  We use the address of the RELLO reloc
@@ -9573,7 +9584,12 @@ md_apply_fix (fixP, valueP)
     case BFD_RELOC_PCREL_LO16:
       /* The addend for this is tricky if it is internal, so we just
 	 do everything here rather than in bfd_install_relocation.  */
-      if ((symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour 
+	  && !fixP->fx_done
+	  && value != 0)
+	break;
+      if (fixP->fx_addsy
+	  && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
 	value += fixP->fx_frag->fr_address + fixP->fx_where;
       buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
       if (target_big_endian)
@@ -9655,6 +9671,15 @@ md_apply_fix (fixP, valueP)
       if ((value & 0x3) != 0)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
 		      _("Branch to odd address (%lx)"), value);
+
+      if (!fixP->fx_done && value != 0)
+	break;
+      /* If 'value' is zero, the remaining reloc code won't actually
+	 do the store, so it must be done here.  This is probably
+	 a bug somewhere.  */
+      if (!fixP->fx_done)
+	value -= fixP->fx_frag->fr_address + fixP->fx_where;
+      
       value >>= 2;
 
       /* update old instruction data */
@@ -11015,6 +11040,8 @@ tc_gen_reloc (section, fixp)
 	as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
       fixp->fx_r_type = BFD_RELOC_GPREL32;
     }
+  else if (fixp->fx_pcrel == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+    reloc->addend = fixp->fx_addnumber;
   else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
     {
       /* We use a special addend for an internal RELLO reloc.  */
@@ -11039,8 +11066,6 @@ tc_gen_reloc (section, fixp)
 			 + fixp->fx_next->fx_frag->fr_address
 			 + fixp->fx_next->fx_where);
     }
-  else if (fixp->fx_pcrel == 0)
-    reloc->addend = fixp->fx_addnumber;
   else
     {
       if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
@@ -11179,7 +11204,8 @@ tc_gen_reloc (section, fixp)
   /* To support a PC relative reloc when generating embedded PIC code
      for ECOFF, we use a Cygnus extension.  We check for that here to
      make sure that we don't let such a reloc escape normally.  */
-  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+  if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+       || OUTPUT_FLAVOR == bfd_target_elf_flavour)
       && code == BFD_RELOC_16_PCREL_S2
       && mips_pic != EMBEDDED_PIC)
     reloc->howto = NULL;
@@ -11814,6 +11840,3 @@ s_loc (x)
   symbolP->sy_segment = now_seg;
 }
 #endif
-
-
-  
md5sum: 37d34bce8da7947c 0ff51ebc71fe4543 3679
--- /sloth/disk0/co/binutils-mainline/binutils/gas/testsuite/gas/mips/mips.exp	Thu Oct  7 12:50:09 1999
+++ binutils/gas/testsuite/gas/mips/mips.exp	Sat Oct 30 17:02:43 1999
@@ -107,5 +107,6 @@ if [istarget mips*-*-*] then {
 	} {
 	    run_dump_test "e32-rel2" 
 	} 
+	run_dump_test "empic"
     }
 }
--- /dev/null	Sat Oct 30 17:13:12 1999
+++ binutils/gas/testsuite/gas/mips/empic.s	Sat Oct 30 17:04:53 1999
@@ -0,0 +1,112 @@
+# Check GNU-specific embedded relocs, for ELF.
+
+	.text
+	.set noreorder
+	nop
+l2:	jal	g1		# R_MIPS_GNU_REL16_S2	g1   -1
+	nop
+	b	g2		# R_MIPS_GNU_REL16_S2	g2   -1
+	nop
+	b	g2		# R_MIPS_GNU_REL16_S2	g2   -1
+	nop
+	jal	l1		# R_MIPS_GNU_REL16_S2	.foo 3F
+	nop
+	jal	l2		# R_MIPS_GNU_REL16_S2	.text 0  or -9
+	nop
+	b	l1+8		# R_MIPS_GNU_REL16_S2	.foo 41
+	nop
+l3:
+	b	l2		# R_MIPS_GNU_REL16_S2	.text 0  or -D
+	nop
+	la	$3,g1-l3	# R_MIPS_GNU_REL_HI16   g1   0
+				# R_MIPS_GNU_REL_LO16   g1   C
+	la	$3,l1-l3	# R_MIPS_GNU_REL_HI16   .foo 0
+				# R_MIPS_GNU_REL_LO16   .foo 114
+	la	$3,l2-l3	# -30
+	.word	g1		# R_MIPS_32	g1    0
+	.word	l1		# R_MIPS_32	.foo  100
+	.word	l2		# R_MIPS_32	.text 4
+	.word	g1-l3		# R_MIPS_PC32	g1    28
+	.word	l1-l3		# R_MIPS_PC32	.foo  12C
+	.word	l2-l3		# -30
+	.align 3
+	.dword	g1		# R_MIPS_64	g1    0
+	.dword	l1		# R_MIPS_64	.foo  100
+	.dword	l2		# R_MIPS_64	.text 4
+	.dword	g1-l3		# R_MIPS_PC64	g1    4C
+	.dword	l1-l3		# R_MIPS_PC64	.foo  154
+	.dword	l2-l3		# -30
+l5:
+	b	2f		# R_MIPS_GNU_REL16_S2	.text 32
+	b	2f+4		# R_MIPS_GNU_REL16_S2	.text 33
+	la	$3,2f-l5	# R_MIPS_GNU_REL_HI16	.text 0
+				# R_MIPS_GNU_REL_HI16	.text D8
+	la	$3,2f+8-l5	# R_MIPS_GNU_REL_HI16	.text 0
+				# R_MIPS_GNU_REL_HI16	.text E8
+
+	.word	2f		# R_MIPS_32	.text CC
+	.word	2f-l5		# R_MIPS_PC32	.text EC  or 34
+	.dword	2f		# R_MIPS_64	.text CC
+	.dword	2f-l5		# R_MIPS_PC64	.text F8  or 34
+	nop
+2:				# at address 0xCC.
+	b	2b		# R_MIPS_GNU_REL16_S2	.text 32
+	b	2b+4		# R_MIPS_GNU_REL16_S2	.text 33
+	la	$3,2b-l5	# R_MIPS_GNU_REL_HI16	.text 0
+				# R_MIPS_GNU_REL_HI16	.text 10C
+	la	$3,2b+8-l5	# R_MIPS_GNU_REL_HI16	.text 0
+				# R_MIPS_GNU_REL_HI16	.text 11C
+	.word	2b		# R_MIPS_32	.text CC
+	.word	2b-l5		# R_MIPS_PC32	.text 11C  or 34
+	nop
+	.dword	2b		# R_MIPS_64	.text CC
+	.dword	2b-l5		# R_MIPS_PC64	.text 98  or 34
+	
+	.section ".foo","ax",@progbits
+	nop
+l4:	
+	la	$3,g1-l4
+	la	$3,l1-l4
+	la	$3,l2-l4
+	la	$3,g1-l4
+
+	dla	$3,g1-l4
+	dla	$3,l1-l4
+	dla	$3,l2-l4
+
+	.word	g1
+	.word	l1
+	.word	l2
+	.word	g1-l4
+	.word	l1-l4
+	.word	l2-l4
+	.dword	g1
+	.dword	l1
+	.dword	l2
+	.dword	g1-l4
+	.dword	l1-l4
+	.dword	l2-l4
+
+	la	$3,g1-l4+4
+	la	$3,l1-l4+4
+	la	$3,l2-l4+4
+
+	dla	$3,g1-l4+4
+	dla	$3,l1-l4+4
+	dla	$3,l2-l4+4
+
+	.word	g1+4
+	.word	l1+4
+	.word	l2+4
+	.word	g1-l4+4
+	.word	l1-l4+4
+	.word	l2-l4+4
+	.dword	g1+4
+	.dword	l1+4
+	.dword	l2+4
+	.dword	g1-l4+4
+	.dword	l1-l4+4
+	.dword	l2-l4+4
+l1:
+
+	nop
--- /dev/null	Sat Oct 30 17:13:12 1999
+++ binutils/gas/testsuite/gas/mips/empic.d	Sat Oct 30 17:12:40 1999
@@ -0,0 +1,155 @@
+#objdump: -rst -mmips:4000
+#name: MIPS empic
+#as: -membedded-pic -mips3
+
+# Check GNU-specific embedded relocs, for ELF.
+
+.*: +file format elf.*mips.*
+
+SYMBOL TABLE:
+0+0000000 l    d  \.text	0+0000000 
+0+0000000 l    d  \.data	0+0000000 
+0+0000000 l    d  \.bss	0+0000000 
+0+0000000 l    d  \.foo	0+0000000 
+0+0000000 l    d  \.reginfo	0+0000000 
+0+0000000 l    d  \.mdebug	0+0000000 
+0+0000004 l       \.text	0+0000000 l2
+0+0000000         \*UND\*	0+0000000 g1
+0+0000000         \*UND\*	0+0000000 g2
+0+0000100 l       \.foo	0+0000000 l1
+0+0000034 l       \.text	0+0000000 l3
+0+0000098 l       \.text	0+0000000 l5
+0+0000004 l       \.foo	0+0000000 l4
+
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET           TYPE              VALUE 
+0+0000004 R_MIPS_GNU_REL16_S2  g1
+0+000000c R_MIPS_GNU_REL16_S2  g2
+0+0000014 R_MIPS_GNU_REL16_S2  g2
+0+000001c R_MIPS_GNU_REL16_S2  \.foo
+0+0000024 R_MIPS_GNU_REL16_S2  \.text
+0+000002c R_MIPS_GNU_REL16_S2  \.foo
+0+0000034 R_MIPS_GNU_REL16_S2  \.text
+0+000003c R_MIPS_GNU_REL_HI16  g1
+0+0000040 R_MIPS_GNU_REL_LO16  g1
+0+0000044 R_MIPS_GNU_REL_HI16  \.foo
+0+0000048 R_MIPS_GNU_REL_LO16  \.foo
+0+0000050 R_MIPS_32         g1
+0+0000054 R_MIPS_32         \.foo
+0+0000058 R_MIPS_32         \.text
+0+000005c R_MIPS_PC32       g1
+0+0000060 R_MIPS_PC32       \.foo
+0+0000068 R_MIPS_64         g1
+0+0000070 R_MIPS_64         \.foo
+0+0000078 R_MIPS_64         \.text
+0+0000080 R_MIPS_PC64       g1
+0+0000088 R_MIPS_PC64       \.foo
+0+0000098 R_MIPS_GNU_REL16_S2  \.text
+0+000009c R_MIPS_GNU_REL16_S2  \.text
+0+00000a0 R_MIPS_GNU_REL_HI16  \.text
+0+00000a4 R_MIPS_GNU_REL_LO16  \.text
+0+00000a8 R_MIPS_GNU_REL_HI16  \.text
+0+00000ac R_MIPS_GNU_REL_LO16  \.text
+0+00000b0 R_MIPS_32         \.text
+0+00000b8 R_MIPS_64         \.text
+0+00000cc R_MIPS_GNU_REL16_S2  \.text
+0+00000d0 R_MIPS_GNU_REL16_S2  \.text
+0+00000d4 R_MIPS_GNU_REL_HI16  \.text
+0+00000d8 R_MIPS_GNU_REL_LO16  \.text
+0+00000dc R_MIPS_GNU_REL_HI16  \.text
+0+00000e0 R_MIPS_GNU_REL_LO16  \.text
+0+00000e4 R_MIPS_32         \.text
+0+00000f0 R_MIPS_64         \.text
+
+
+RELOCATION RECORDS FOR \[\.foo\]:
+OFFSET           TYPE              VALUE 
+0+0000004 R_MIPS_GNU_REL_HI16  g1
+0+0000008 R_MIPS_GNU_REL_LO16  g1
+0+000000c R_MIPS_GNU_REL_HI16  \.foo
+0+0000010 R_MIPS_GNU_REL_LO16  \.foo
+0+0000014 R_MIPS_GNU_REL_HI16  \.text
+0+0000018 R_MIPS_GNU_REL_LO16  \.text
+0+000001c R_MIPS_GNU_REL_HI16  g1
+0+0000020 R_MIPS_GNU_REL_LO16  g1
+0+0000024 R_MIPS_GNU_REL_HI16  g1
+0+0000028 R_MIPS_GNU_REL_LO16  g1
+0+000002c R_MIPS_GNU_REL_HI16  \.foo
+0+0000030 R_MIPS_GNU_REL_LO16  \.foo
+0+0000034 R_MIPS_GNU_REL_HI16  \.text
+0+0000038 R_MIPS_GNU_REL_LO16  \.text
+0+000003c R_MIPS_32         g1
+0+0000040 R_MIPS_32         \.foo
+0+0000044 R_MIPS_32         \.text
+0+0000048 R_MIPS_PC32       g1
+0+0000050 R_MIPS_PC32       \.text
+0+0000058 R_MIPS_64         g1
+0+0000060 R_MIPS_64         \.foo
+0+0000068 R_MIPS_64         \.text
+0+0000070 R_MIPS_PC64       g1
+0+0000080 R_MIPS_PC64       \.text
+0+0000088 R_MIPS_GNU_REL_HI16  g1
+0+000008c R_MIPS_GNU_REL_LO16  g1
+0+0000090 R_MIPS_GNU_REL_HI16  \.foo
+0+0000094 R_MIPS_GNU_REL_LO16  \.foo
+0+0000098 R_MIPS_GNU_REL_HI16  \.text
+0+000009c R_MIPS_GNU_REL_LO16  \.text
+0+00000a0 R_MIPS_GNU_REL_HI16  g1
+0+00000a4 R_MIPS_GNU_REL_LO16  g1
+0+00000a8 R_MIPS_GNU_REL_HI16  \.foo
+0+00000ac R_MIPS_GNU_REL_LO16  \.foo
+0+00000b0 R_MIPS_GNU_REL_HI16  \.text
+0+00000b4 R_MIPS_GNU_REL_LO16  \.text
+0+00000b8 R_MIPS_32         g1
+0+00000bc R_MIPS_32         \.foo
+0+00000c0 R_MIPS_32         \.text
+0+00000c4 R_MIPS_PC32       g1
+0+00000cc R_MIPS_PC32       \.text
+0+00000d0 R_MIPS_64         g1
+0+00000d8 R_MIPS_64         \.foo
+0+00000e0 R_MIPS_64         \.text
+0+00000e8 R_MIPS_PC64       g1
+0+00000f8 R_MIPS_PC64       \.text
+
+Contents of section \.text:
+ 0000 00000000 0411ffff 00000000 1000ffff  .*
+ 0010 00000000 1000ffff 00000000 0411003f  .*
+ 0020 00000000 04110000 00000000 10000041  .*
+ 0030 00000000 10000000 00000000 3c030000  .*
+ 0040 [26]463000c 3c030000 [26]4630114 2403ffd0  .*
+ 0050 00000000 00000100 00000004 00000028  .*
+ 0060 0000012c ffffffd0 00000000 00000000  .*
+ 0070 00000000 00000100 00000000 00000004  .*
+ 0080 00000000 0000004c 00000000 00000154  .*
+ 0090 ffffffff ffffffd0 10000032 10000033  .*
+ 00a0 3c030000 [26]46300d8 3c030000 [26]46300e8  .*
+ 00b0 000000cc 00000034 00000000 000000cc  .*
+ 00c0 00000000 00000034 00000000 10000032  .*
+ 00d0 10000033 3c030000 [26]463010c 3c030000  .*
+ 00e0 [26]463011c 000000cc 00000034 00000000  .*
+ 00f0 00000000 000000cc 00000000 00000034  .*
+Contents of section \.data:
+Contents of section \.reginfo:
+ 0000 80000008 00000000 00000000 00000000  .*
+ 0010 00000000 00000000                    .*
+Contents of section \.mdebug:
+#...
+Contents of section \.foo:
+ 0000 00000000 3c030000 [26]4630004 3c030000  .*
+ 0010 [26]463010c 3c030000 [26]4630018 3c030000  .*
+ 0020 [26]463001c 3c030000 [26]4630024 3c030000  .*
+ 0030 [26]463012c 3c030000 [26]4630038 00000000  .*
+ 0040 00000100 00000004 00000044 000000fc  .*
+ 0050 00000050 00000000 00000000 00000000  .*
+ 0060 00000000 00000100 00000000 00000004  .*
+ 0070 00000000 0000006c 00000000 000000fc  .*
+ 0080 00000000 00000080 3c030000 [26]463008c  .*
+ 0090 3c030000 [26]4630194 3c030000 [26]46300a0  .*
+ 00a0 3c030000 [26]46300a4 3c030000 [26]46301ac  .*
+ 00b0 3c030000 [26]46300b8 00000004 00000104  .*
+ 00c0 00000008 000000c4 00000100 000000d0  .*
+ 00d0 00000000 00000004 00000000 00000104  .*
+ 00e0 00000000 00000008 00000000 000000e8  .*
+ 00f0 00000000 00000100 00000000 000000fc  .*
+ 0100 00000000                             .*
md5sum: 8dfaa537e9578958 c6674368f03c8bd6 25843
--- /sloth/disk0/co/binutils-mainline/binutils/include/elf/mips.h	Mon Jun 21 16:57:35 1999
+++ binutils/include/elf/mips.h	Sat Oct 30 17:04:53 1999
@@ -75,6 +75,12 @@ START_RELOC_NUMBERS (elf_mips_reloc_type
   /* These relocs are used for the mips16.  */
   RELOC_NUMBER (R_MIPS16_26, 100)
   RELOC_NUMBER (R_MIPS16_GPREL, 101)
+  /* These are GNU extensions to handle embedded-pic.  */
+  RELOC_NUMBER (R_MIPS_PC32, 248)
+  RELOC_NUMBER (R_MIPS_PC64, 249)
+  RELOC_NUMBER (R_MIPS_GNU_REL16_S2, 250)
+  RELOC_NUMBER (R_MIPS_GNU_REL_LO16, 251)
+  RELOC_NUMBER (R_MIPS_GNU_REL_HI16, 252)
   /* These are GNU extensions to enable C++ vtable garbage collection.  */
   RELOC_NUMBER (R_MIPS_GNU_VTINHERIT, 253)
   RELOC_NUMBER (R_MIPS_GNU_VTENTRY, 254)
============================================================

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