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]

MIPS ELF embedded-pic support.



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.

By far the most suspicious part is the bit under '#ifdef OBJ_ELF' in
md_apply_fix in the assembler that reads
+	  if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
+	      || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
I know it's necessary, but I don't know why this reloc should be
different to any of the others.

There's some gcc support needed to allow all the features of ELF (like
constructors and linkonce sections) to work, but plain C should be
working already.

OK to commit?

-- 
Geoffrey Keating <geoffk@cygnus.com>

===File ~/patches/cygnus/tx49-bin-empic.patch===============
md5sum: 55be010e980adf7c d8451e3d02061503 197737
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: 6c90f798e27bdcd1 5c9890c40585fcf7 165334
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 (append_insn): The ELF linker doesn't
	do branch relaxation (yet).
	(mips_force_relocation): Likewise.
	(SWITCH_TABLE): The ELF embedded-pic implementation thus 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: c552a0030714e084 1e4c3b22d6476d31 84478
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	Fri Oct 15 15:42:54 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: 36b310b7eac9fea2 38ae000d53f4a00a 333165
--- /sloth/disk0/co/binutils-mainline/binutils/gas/config/tc-mips.c	Tue Sep 28 14:05:41 1999
+++ binutils/gas/config/tc-mips.c	Fri Oct 15 15:42:53 1999
@@ -2062,9 +2062,11 @@ append_insn (place, ip, address_expr, re
 		  && insn_uses_reg (&prev_insn, RA, MIPS_GR_REG))
 	      /* If we are generating embedded PIC code, the branch
 		 might be expanded into a sequence which uses $at, so
-		 we can't swap with an instruction which reads it.  */
+		 we can't swap with an instruction which reads it.  
+		 The ELF linker doesn't do this at present.  */
 	      || (mips_pic == EMBEDDED_PIC
-		  && insn_uses_reg (&prev_insn, AT, MIPS_GR_REG))
+		  && insn_uses_reg (&prev_insn, AT, MIPS_GR_REG)
+		  && OUTPUT_FLAVOR != bfd_target_elf_flavour)
 	      /* If the previous previous instruction has a load
 		 delay, and sets a register that the branch reads, we
 		 can not swap.  */
@@ -2542,7 +2544,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;
 
@@ -2556,7 +2557,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)
 	    {
@@ -4095,23 +4095,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);
@@ -4725,9 +4725,10 @@ macro (ip)
       else if (mips_pic == EMBEDDED_PIC)
 	{
 	  macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p");
-	  /* The linker may expand the call to a longer sequence which
-	     uses $at, so we must break rather than return.  */
-	  break;
+	  if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+	    /* The linker may expand the call to a longer sequence which
+	       uses $at, so we must break rather than return.  */
+	    break;
 	}
       else
 	abort ();
@@ -7633,11 +7634,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
@@ -7780,9 +7785,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')
@@ -9423,6 +9427,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 \
@@ -9442,6 +9447,7 @@ mips_force_relocation (fixp)
     return 1;
 
   return (mips_pic == EMBEDDED_PIC
+	  && OUTPUT_FLAVOR != bfd_target_elf_flavour
 	  && (fixp->fx_pcrel
 	      || SWITCH_TABLE (fixp)
 	      || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S
@@ -9470,29 +9476,28 @@ 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);
-          }
-      }
+      if (fixP->fx_pcrel)
+	{
+	  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 */
 
   if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel)
@@ -9529,7 +9534,10 @@ 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)
+	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
@@ -9549,7 +9557,10 @@ 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)
+	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)
@@ -9631,6 +9642,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 */
@@ -10991,6 +11011,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.  */
@@ -11015,8 +11037,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)
@@ -11155,7 +11175,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;
@@ -11790,6 +11811,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	Fri Oct 15 15:42:53 1999
@@ -107,5 +107,6 @@ if [istarget mips*-*-*] then {
 	} {
 	    run_dump_test "e32-rel2" 
 	} 
+	run_dump_test "empic"
     }
 }
--- /dev/null	Fri Oct 15 15:39:15 1999
+++ binutils/gas/testsuite/gas/mips/empic.s	Fri Oct 15 15:42:53 1999
@@ -0,0 +1,87 @@
+# 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		# -9
+	nop
+	b	l1+8		# R_MIPS_GNU_REL16_S2	.foo 41
+	nop
+l3:	
+	b	l2		# -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
+
+	.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	Fri Oct 15 15:39:15 1999
+++ binutils/gas/testsuite/gas/mips/empic.d	Fri Oct 15 15:42:53 1999
@@ -0,0 +1,122 @@
+#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+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+000002c R_MIPS_GNU_REL16_S2  \.foo
+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
+
+
+RELOCATION RECORDS FOR \[\.foo\]:
+OFFSET           TYPE              VALUE 
+0+0000004 R_MIPS_GNU_REL_HI16  g1
+0+0000008 R_MIPS_GNU_REL_LO16  g1
+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+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+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+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 0411fff7 00000000 10000041  .*
+ 0030 00000000 1000fff3 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                    .*
+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]46300fc 3c030000 [26]4630018 3c030000  .*
+ 0020 [26]463001c 3c030000 [26]4630024 3c030000  .*
+ 0030 [26]46300fc 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]4630100 3c030000 [26]46300a0  .*
+ 00a0 3c030000 [26]46300a4 3c030000 [26]4630100  .*
+ 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 fc736b59abca438f 25843
--- /sloth/disk0/co/binutils-mainline/binutils/include/elf/mips.h	Mon Jun 21 16:57:35 1999
+++ binutils/include/elf/mips.h	Fri Oct 15 15:42:53 1999
@@ -78,6 +78,12 @@ START_RELOC_NUMBERS (elf_mips_reloc_type
   /* These are GNU extensions to enable C++ vtable garbage collection.  */
   RELOC_NUMBER (R_MIPS_GNU_VTINHERIT, 253)
   RELOC_NUMBER (R_MIPS_GNU_VTENTRY, 254)
+  /* These are GNU extensions to handle embedded-pic.  */
+  RELOC_NUMBER (R_MIPS_GNU_REL_HI16, 252)
+  RELOC_NUMBER (R_MIPS_GNU_REL_LO16, 251)
+  RELOC_NUMBER (R_MIPS_GNU_REL16_S2, 250)
+  RELOC_NUMBER (R_MIPS_PC64, 249)
+  RELOC_NUMBER (R_MIPS_PC32, 248)
 END_RELOC_NUMBERS
 
 /* Processor specific flags for the ELF header e_flags field.  */
============================================================

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