[PATCH] MIPS/BFD: Handle linker garbage collection with n64 relocs

Maciej W. Rozycki macro@linux-mips.org
Sun Apr 29 03:02:00 GMT 2012


On Tue, 10 Apr 2012, Richard Sandiford wrote:

> >  The fix below removes the problem and causes no regressions with said 
> > modified mips64-linux-gnu configuration nor a pristine mips-linux-gnu one.  
> > The RELOC_AGAINST_DISCARDED_SECTION macro has a bit weird semantics, it's 
> > not really intended to behave like a function call, and I think there's 
> > little point in making it do (e.g. adding argument protection throughout), 
> > if at all possible.  Therefore some unusual syntactic sugar had to be 
> > added around the macro reference, so that its expansion can be executed 
> > three times consecutively over a relocation triplet.  This is explained in 
> > the comment included with the change itself.  The new code also avoids a 
> > duplicate call to MIPS_ELF_RTYPE_TO_HOWTO, hence a bit unusual form of the 
> > loop introduced.
> 
> I think it'd be better (and cleaner) to handle
> bed->s->int_rels_per_ext_rel in RELOC_AGAINST_DISCARDED_SECTION
> instead.

 Hmm, good point, really.

> The patch as posted isn't quite correct, because the "middle"
> relocation in a triple doesn't define a relocation field.
> E.g. for the common %hi(%neg(%gp_rel(...))) case, the middle
> %neg is a 64-bit relocation, but we don't want R_A_D_S to clear
> a 64-bit field.

 This is a good observation as well.  I think this should be handled in a 
general manner and given that it's the final relocation (outermost percent 
operator) that determines the output field of the whole relocation 
operation, it's that one that should be picked for this purpose -- which 
is the last non-null one.

 So here's the resulting change, but obviously because of the API change 
of RELOC_AGAINST_DISCARDED_SECTION it now touches virtually everything.  
As the selection of the correct relocation for output relocatable field 
clearing is target-specific (I think; let me know it you have reasons to 
believe otherwise), I have decided there is no feasible way to do it 
within RELOC_AGAINST_DISCARDED_SECTION, and decided to pass the right 
HOWTO and the REL-relative index of the relocation that HOWTO applies to 
as extra arguments to RELOC_AGAINST_DISCARDED_SECTION.

 Also I've decided to keep mips_reloc_against_discarded_section to avoid 
stretching _bfd_mips_elf_relocate_section even further as it's IMHO 
already beyond a reasonable size for a function, but I can fold it back if 
you preferred it that way.

 This fixes the original problem just as the previous version did.  OK in 
this form?

2012-04-28  Maciej W. Rozycki  <macro@linux-mips.org>

	bfd/
	* elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Handle compound
	relocations.
	* elfxx-mips.c (mips_reloc_against_discarded_section): New
	function.
	(_bfd_mips_elf_relocate_section): Call it, in place of
	RELOC_AGAINST_DISCARDED_SECTION.
	* elf-m10200.c (mn10200_elf_relocate_section): Update arguments
	to RELOC_AGAINST_DISCARDED_SECTION.
	* elf-m10300.c (mn10300_elf_relocate_section): Likewise.
	* elf32-arm.c (elf32_arm_relocate_section): Likewise.
	* elf32-avr.c (elf32_avr_relocate_section): Likewise.
	* elf32-bfin.c (bfin_relocate_section): Likewise.
	(bfinfdpic_relocate_section): Likewise.
	* elf32-cr16.c (elf32_cr16_relocate_section): Likewise.
	* elf32-cr16c.c (elf32_cr16c_relocate_section): Likewise.
	* elf32-cris.c (cris_elf_relocate_section): Likewise.
	* elf32-crx.c (elf32_crx_relocate_section): Likewise.
	* elf32-d10v.c (elf32_d10v_relocate_section): Likewise.
	* elf32-epiphany.c (epiphany_elf_relocate_section): Likewise.
	* elf32-fr30.c (fr30_elf_relocate_section): Likewise.
	* elf32-frv.c (elf32_frv_relocate_section): Likewise.
	* elf32-h8300.c (elf32_h8_relocate_section): Likewise.
	* elf32-hppa.c (elf32_hppa_relocate_section): Likewise.
	* elf32-i370.c (i370_elf_relocate_section): Likewise.
	* elf32-i386.c (elf_i386_relocate_section): Likewise.
	* elf32-i860.c (elf32_i860_relocate_section): Likewise.
	* elf32-ip2k.c (ip2k_elf_relocate_section): Likewise.
	* elf32-iq2000.c (iq2000_elf_relocate_section): Likewise.
	* elf32-lm32.c (lm32_elf_relocate_section): Likewise.
	* elf32-m32c.c (m32c_elf_relocate_section): Likewise.
	* elf32-m32r.c (m32r_elf_relocate_section): Likewise.
	* elf32-m68hc1x.c (elf32_m68hc11_relocate_section): Likewise.
	* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
	* elf32-mcore.c (mcore_elf_relocate_section): Likewise.
	* elf32-mep.c (mep_elf_relocate_section): Likewise.
	* elf32-moxie.c (moxie_elf_relocate_section): Likewise.
	* elf32-msp430.c (elf32_msp430_relocate_section): Likewise.
	* elf32-mt.c (mt_elf_relocate_section): Likewise.
	* elf32-openrisc.c (openrisc_elf_relocate_section): Likewise.
	* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
	* elf32-rl78.c (rl78_elf_relocate_section): Likewise.
	* elf32-rx.c (rx_elf_relocate_section): Likewise.
	* elf32-s390.c (elf_s390_relocate_section): Likewise.
	* elf32-score.c (s3_bfd_score_elf_relocate_section): Likewise.
	* elf32-score7.c (s7_bfd_score_elf_relocate_section): Likewise.
	* elf32-sh.c (sh_elf_relocate_section): Likewise.
	* elf32-spu.c (spu_elf_relocate_section): Likewise.
	* elf32-tic6x.c (elf32_tic6x_relocate_section): Likewise.
	* elf32-tilepro.c (tilepro_elf_relocate_section): Likewise.
	* elf32-v850.c (v850_elf_relocate_section): Likewise.
	* elf32-vax.c (elf_vax_relocate_section): Likewise.
	* elf32-xc16x.c (elf32_xc16x_relocate_section): Likewise.
	* elf32-xstormy16.c (xstormy16_elf_relocate_section): Likewise.
	* elf32-xtensa.c (elf_xtensa_relocate_section): Likewise.
	* elf64-alpha.c (elf64_alpha_relocate_section_r): Likewise.
	(elf64_alpha_relocate_section): Likewise.
	* elf64-hppa.c (elf64_hppa_relocate_section): Likewise.
	* elf64-mmix.c (mmix_elf_relocate_section): Likewise.
	* elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
	* elf64-s390.c (elf_s390_relocate_section): Likewise.
	* elf64-sh64.c (sh_elf64_relocate_section): Likewise.
	* elf64-x86-64.c (elf_x86_64_relocate_section): Likewise.
	* elfnn-ia64.c (elfNN_ia64_relocate_section): Likewise.
	* elfxx-sparc.c (_bfd_sparc_elf_relocate_section): Likewise.
	* elfxx-tilegx.c (tilegx_elf_relocate_section): Likewise.

  Maciej

binutils-mips64-reloc-discard.patch
Index: binutils/bfd/elf-bfd.h
===================================================================
--- binutils.orig/bfd/elf-bfd.h
+++ binutils/bfd/elf-bfd.h
@@ -2408,10 +2408,11 @@ extern asection _bfd_elf_large_com_secti
    link, we remove such relocations.  Otherwise, we just want the
    section contents zeroed and avoid any special processing.  */
 #define RELOC_AGAINST_DISCARDED_SECTION(info, input_bfd, input_section,	\
-					rel, relend, howto, contents)	\
+					rel, count, relend,		\
+					howto, index, contents)		\
   {									\
     _bfd_clear_contents (howto, input_bfd, input_section,		\
-			 contents + rel->r_offset);			\
+			 contents + rel[index].r_offset);		\
 									\
     if (info->relocatable						\
 	&& (input_section->flags & SEC_DEBUGGING))			\
@@ -2423,23 +2424,28 @@ extern asection _bfd_elf_large_com_secti
 	rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section); \
 									\
 	/* Avoid empty output section.  */				\
-	if (rel_hdr->sh_size > rel_hdr->sh_entsize)			\
+	if (rel_hdr->sh_size > count * rel_hdr->sh_entsize)		\
 	  {								\
-	    rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
+	    rel_hdr->sh_size -= count * rel_hdr->sh_entsize;		\
 	    rel_hdr = _bfd_elf_single_rel_hdr (input_section);		\
-	    rel_hdr->sh_size -= rel_hdr->sh_entsize;			\
+	    rel_hdr->sh_size -= count * rel_hdr->sh_entsize;		\
 									\
-	    memmove (rel, rel + 1, (relend - rel - 1) * sizeof (*rel));	\
+	    memmove (rel, rel + count,					\
+		     (relend - rel - count) * sizeof (*rel));		\
 									\
-	    input_section->reloc_count--;				\
-	    relend--;							\
+	    input_section->reloc_count -= count;			\
+	    relend -= count;						\
 	    rel--;							\
 	    continue;							\
 	  }								\
       }									\
 									\
-    rel->r_info = 0;							\
-    rel->r_addend = 0;							\
+    for (i = 0; i < count; i++)						\
+      {									\
+	rel[i].r_info = 0;						\
+	rel[i].r_addend = 0;						\
+      }									\
+    rel += count - 1;							\
     continue;								\
   }
 
Index: binutils/bfd/elf-m10200.c
===================================================================
--- binutils.orig/bfd/elf-m10200.c
+++ binutils/bfd/elf-m10200.c
@@ -403,7 +403,7 @@ mn10200_elf_relocate_section (output_bfd
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf-m10300.c
===================================================================
--- binutils.orig/bfd/elf-m10300.c
+++ binutils/bfd/elf-m10300.c
@@ -2117,7 +2117,7 @@ mn10300_elf_relocate_section (bfd *outpu
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-arm.c
===================================================================
--- binutils.orig/bfd/elf32-arm.c
+++ binutils/bfd/elf32-arm.c
@@ -10382,7 +10382,7 @@ elf32_arm_relocate_section (bfd *       
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-avr.c
===================================================================
--- binutils.orig/bfd/elf32-avr.c
+++ binutils/bfd/elf32-avr.c
@@ -1191,7 +1191,7 @@ elf32_avr_relocate_section (bfd *output_
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-bfin.c
===================================================================
--- binutils.orig/bfd/elf32-bfin.c
+++ binutils/bfd/elf32-bfin.c
@@ -1446,7 +1446,7 @@ bfin_relocate_section (bfd * output_bfd,
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
@@ -2667,7 +2667,7 @@ bfinfdpic_relocate_section (bfd * output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-cr16.c
===================================================================
--- binutils.orig/bfd/elf32-cr16.c
+++ binutils/bfd/elf32-cr16.c
@@ -1433,7 +1433,7 @@ elf32_cr16_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
         continue;
Index: binutils/bfd/elf32-cr16c.c
===================================================================
--- binutils.orig/bfd/elf32-cr16c.c
+++ binutils/bfd/elf32-cr16c.c
@@ -725,7 +725,7 @@ elf32_cr16c_relocate_section (bfd *outpu
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-cris.c
===================================================================
--- binutils.orig/bfd/elf32-cris.c
+++ binutils/bfd/elf32-cris.c
@@ -1186,7 +1186,7 @@ cris_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-crx.c
===================================================================
--- binutils.orig/bfd/elf32-crx.c
+++ binutils/bfd/elf32-crx.c
@@ -875,7 +875,7 @@ elf32_crx_relocate_section (bfd *output_
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-d10v.c
===================================================================
--- binutils.orig/bfd/elf32-d10v.c
+++ binutils/bfd/elf32-d10v.c
@@ -465,7 +465,7 @@ elf32_d10v_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-epiphany.c
===================================================================
--- binutils.orig/bfd/elf32-epiphany.c
+++ binutils/bfd/elf32-epiphany.c
@@ -526,7 +526,7 @@ epiphany_elf_relocate_section (bfd *outp
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-fr30.c
===================================================================
--- binutils.orig/bfd/elf32-fr30.c
+++ binutils/bfd/elf32-fr30.c
@@ -579,7 +579,7 @@ fr30_elf_relocate_section (output_bfd, i
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-frv.c
===================================================================
--- binutils.orig/bfd/elf32-frv.c
+++ binutils/bfd/elf32-frv.c
@@ -2814,7 +2814,7 @@ elf32_frv_relocate_section (output_bfd, 
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-h8300.c
===================================================================
--- binutils.orig/bfd/elf32-h8300.c
+++ binutils/bfd/elf32-h8300.c
@@ -462,7 +462,7 @@ elf32_h8_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-hppa.c
===================================================================
--- binutils.orig/bfd/elf32-hppa.c
+++ binutils/bfd/elf32-hppa.c
@@ -3736,8 +3736,8 @@ elf32_hppa_relocate_section (bfd *output
 
       if (sym_sec != NULL && elf_discarded_section (sym_sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rela, relend,
-					 elf_hppa_howto_table + r_type,
+					 rela, 1, relend,
+					 elf_hppa_howto_table + r_type, 0,
 					 contents);
 
       if (info->relocatable)
Index: binutils/bfd/elf32-i370.c
===================================================================
--- binutils.orig/bfd/elf32-i370.c
+++ binutils/bfd/elf32-i370.c
@@ -1133,7 +1133,7 @@ i370_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-i386.c
===================================================================
--- binutils.orig/bfd/elf32-i386.c
+++ binutils/bfd/elf32-i386.c
@@ -3192,7 +3192,7 @@ elf_i386_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-i860.c
===================================================================
--- binutils.orig/bfd/elf32-i860.c
+++ binutils/bfd/elf32-i860.c
@@ -1130,7 +1130,7 @@ elf32_i860_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-ip2k.c
===================================================================
--- binutils.orig/bfd/elf32-ip2k.c
+++ binutils/bfd/elf32-ip2k.c
@@ -1438,7 +1438,7 @@ ip2k_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-iq2000.c
===================================================================
--- binutils.orig/bfd/elf32-iq2000.c
+++ binutils/bfd/elf32-iq2000.c
@@ -635,7 +635,7 @@ iq2000_elf_relocate_section (bfd *		    
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-lm32.c
===================================================================
--- binutils.orig/bfd/elf32-lm32.c
+++ binutils/bfd/elf32-lm32.c
@@ -895,7 +895,7 @@ lm32_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
         {
Index: binutils/bfd/elf32-m32c.c
===================================================================
--- binutils.orig/bfd/elf32-m32c.c
+++ binutils/bfd/elf32-m32c.c
@@ -436,7 +436,7 @@ m32c_elf_relocate_section
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-m32r.c
===================================================================
--- binutils.orig/bfd/elf32-m32r.c
+++ binutils/bfd/elf32-m32r.c
@@ -2615,7 +2615,7 @@ m32r_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable && !use_rel)
 	{
Index: binutils/bfd/elf32-m68hc1x.c
===================================================================
--- binutils.orig/bfd/elf32-m68hc1x.c
+++ binutils/bfd/elf32-m68hc1x.c
@@ -986,7 +986,7 @@ elf32_m68hc11_relocate_section (bfd *out
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-m68k.c
===================================================================
--- binutils.orig/bfd/elf32-m68k.c
+++ binutils/bfd/elf32-m68k.c
@@ -3712,7 +3712,7 @@ elf_m68k_relocate_section (output_bfd, i
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-mcore.c
===================================================================
--- binutils.orig/bfd/elf32-mcore.c
+++ binutils/bfd/elf32-mcore.c
@@ -468,7 +468,7 @@ mcore_elf_relocate_section (bfd * output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-mep.c
===================================================================
--- binutils.orig/bfd/elf32-mep.c
+++ binutils/bfd/elf32-mep.c
@@ -502,7 +502,7 @@ mep_elf_relocate_section
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-moxie.c
===================================================================
--- binutils.orig/bfd/elf32-moxie.c
+++ binutils/bfd/elf32-moxie.c
@@ -252,7 +252,7 @@ moxie_elf_relocate_section (bfd *output_
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-msp430.c
===================================================================
--- binutils.orig/bfd/elf32-msp430.c
+++ binutils/bfd/elf32-msp430.c
@@ -456,7 +456,7 @@ elf32_msp430_relocate_section (bfd * out
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-mt.c
===================================================================
--- binutils.orig/bfd/elf32-mt.c
+++ binutils/bfd/elf32-mt.c
@@ -356,7 +356,7 @@ mt_elf_relocate_section
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-openrisc.c
===================================================================
--- binutils.orig/bfd/elf32-openrisc.c
+++ binutils/bfd/elf32-openrisc.c
@@ -375,7 +375,7 @@ openrisc_elf_relocate_section (bfd *outp
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-ppc.c
===================================================================
--- binutils.orig/bfd/elf32-ppc.c
+++ binutils/bfd/elf32-ppc.c
@@ -6888,7 +6888,7 @@ ppc_elf_relocate_section (bfd *output_bf
 	  if (r_type < R_PPC_max)
 	    howto = ppc_elf_howto_table[r_type];
 	  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					   rel, relend, howto, contents);
+					   rel, 1, relend, howto, 0, contents);
 	}
 
       if (info->relocatable)
Index: binutils/bfd/elf32-rl78.c
===================================================================
--- binutils.orig/bfd/elf32-rl78.c
+++ binutils/bfd/elf32-rl78.c
@@ -473,7 +473,7 @@ rl78_elf_relocate_section
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-rx.c
===================================================================
--- binutils.orig/bfd/elf32-rx.c
+++ binutils/bfd/elf32-rx.c
@@ -523,7 +523,7 @@ rx_elf_relocate_section
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-s390.c
===================================================================
--- binutils.orig/bfd/elf32-s390.c
+++ binutils/bfd/elf32-s390.c
@@ -2302,7 +2302,7 @@ elf_s390_relocate_section (output_bfd, i
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-score.c
===================================================================
--- binutils.orig/bfd/elf32-score.c
+++ binutils/bfd/elf32-score.c
@@ -2674,7 +2674,7 @@ s3_bfd_score_elf_relocate_section (bfd *
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
         {
Index: binutils/bfd/elf32-score7.c
===================================================================
--- binutils.orig/bfd/elf32-score7.c
+++ binutils/bfd/elf32-score7.c
@@ -2445,7 +2445,7 @@ s7_bfd_score_elf_relocate_section (bfd *
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
         {
Index: binutils/bfd/elf32-sh.c
===================================================================
--- binutils.orig/bfd/elf32-sh.c
+++ binutils/bfd/elf32-sh.c
@@ -4239,7 +4239,7 @@ sh_elf_relocate_section (bfd *output_bfd
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-spu.c
===================================================================
--- binutils.orig/bfd/elf32-spu.c
+++ binutils/bfd/elf32-spu.c
@@ -4898,7 +4898,7 @@ spu_elf_relocate_section (bfd *output_bf
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-tic6x.c
===================================================================
--- binutils.orig/bfd/elf32-tic6x.c
+++ binutils/bfd/elf32-tic6x.c
@@ -2329,7 +2329,7 @@ elf32_tic6x_relocate_section (bfd *outpu
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf32-tilepro.c
===================================================================
--- binutils.orig/bfd/elf32-tilepro.c
+++ binutils/bfd/elf32-tilepro.c
@@ -2876,7 +2876,7 @@ tilepro_elf_relocate_section (bfd *outpu
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-v850.c
===================================================================
--- binutils.orig/bfd/elf32-v850.c
+++ binutils/bfd/elf32-v850.c
@@ -2095,7 +2095,7 @@ v850_elf_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-vax.c
===================================================================
--- binutils.orig/bfd/elf32-vax.c
+++ binutils/bfd/elf32-vax.c
@@ -1445,7 +1445,7 @@ elf_vax_relocate_section (bfd *output_bf
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-xc16x.c
===================================================================
--- binutils.orig/bfd/elf32-xc16x.c
+++ binutils/bfd/elf32-xc16x.c
@@ -389,7 +389,7 @@ elf32_xc16x_relocate_section (bfd *outpu
 	  reloc_howto_type *howto;
 	  howto = xc16x_reloc_type_lookup (input_bfd, r_type);
 	  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					   rel, relend, howto, contents);
+					   rel, 1, relend, howto, 0, contents);
 	}
 
       if (info->relocatable)
Index: binutils/bfd/elf32-xstormy16.c
===================================================================
--- binutils.orig/bfd/elf32-xstormy16.c
+++ binutils/bfd/elf32-xstormy16.c
@@ -827,7 +827,7 @@ xstormy16_elf_relocate_section (bfd *   
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf32-xtensa.c
===================================================================
--- binutils.orig/bfd/elf32-xtensa.c
+++ binutils/bfd/elf32-xtensa.c
@@ -2658,7 +2658,7 @@ elf_xtensa_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf64-alpha.c
===================================================================
--- binutils.orig/bfd/elf64-alpha.c
+++ binutils/bfd/elf64-alpha.c
@@ -4109,8 +4109,8 @@ elf64_alpha_relocate_section_r (bfd *out
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend,
-					 elf64_alpha_howto_table + r_type,
+					 rel, 1, relend,
+					 elf64_alpha_howto_table + r_type, 0,
 					 contents);
 
       if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
@@ -4318,7 +4318,7 @@ elf64_alpha_relocate_section (bfd *outpu
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       addend = rel->r_addend;
       value += addend;
Index: binutils/bfd/elf64-hppa.c
===================================================================
--- binutils.orig/bfd/elf64-hppa.c
+++ binutils/bfd/elf64-hppa.c
@@ -3921,7 +3921,7 @@ elf64_hppa_relocate_section (bfd *output
 
       if (sym_sec != NULL && elf_discarded_section (sym_sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf64-mmix.c
===================================================================
--- binutils.orig/bfd/elf64-mmix.c
+++ binutils/bfd/elf64-mmix.c
@@ -1477,7 +1477,7 @@ mmix_elf_relocate_section (output_bfd, i
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	{
Index: binutils/bfd/elf64-ppc.c
===================================================================
--- binutils.orig/bfd/elf64-ppc.c
+++ binutils/bfd/elf64-ppc.c
@@ -12257,8 +12257,8 @@ ppc64_elf_relocate_section (bfd *output_
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend,
-					 ppc64_elf_howto_table[r_type],
+					 rel, 1, relend,
+					 ppc64_elf_howto_table[r_type], 0,
 					 contents);
 
       if (info->relocatable)
Index: binutils/bfd/elf64-s390.c
===================================================================
--- binutils.orig/bfd/elf64-s390.c
+++ binutils/bfd/elf64-s390.c
@@ -2246,7 +2246,7 @@ elf_s390_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf64-sh64.c
===================================================================
--- binutils.orig/bfd/elf64-sh64.c
+++ binutils/bfd/elf64-sh64.c
@@ -1663,7 +1663,7 @@ sh_elf64_relocate_section (bfd *output_b
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elf64-x86-64.c
===================================================================
--- binutils.orig/bfd/elf64-x86-64.c
+++ binutils/bfd/elf64-x86-64.c
@@ -3145,7 +3145,7 @@ elf_x86_64_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elfnn-ia64.c
===================================================================
--- binutils.orig/bfd/elfnn-ia64.c
+++ binutils/bfd/elfnn-ia64.c
@@ -3921,7 +3921,7 @@ elfNN_ia64_relocate_section (bfd *output
 
       if (sym_sec != NULL && elf_discarded_section (sym_sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elfxx-mips.c
===================================================================
--- binutils.orig/bfd/elfxx-mips.c
+++ binutils/bfd/elfxx-mips.c
@@ -9324,6 +9324,55 @@ mips_elf_adjust_addend (bfd *output_bfd,
     }
 }
 
+/* Handle relocations against symbols from removed linkonce sections,
+   or sections discarded by a linker script.  We use this wrapper around
+   RELOC_AGAINST_DISCARDED_SECTION to handle triplets of compound relocs
+   on 64-bit ELF targets.  In this case for any relocation handled, which
+   always be the first in a triplet, the remaining two have to be processed
+   together with the first, even if they are R_MIPS_NONE.  It is the symbol
+   index referred by the first reloc that applies to all the three and the
+   remaining two never refer to an object symbol.  And it is the final
+   relocation (the last non-null one) that determines the output field of
+   the whole relocation so retrieve the corresponding howto structure for
+   the relocatable field to be cleared by RELOC_AGAINST_DISCARDED_SECTION.
+
+   Note that RELOC_AGAINST_DISCARDED_SECTION is a macro that uses "continue"
+   and therefore requires to be pasted in a loop.  It also defines a block
+   and does not protect any of its arguments, hence the extra brackets.  */
+
+static void
+mips_reloc_against_discarded_section (bfd *output_bfd,
+				      struct bfd_link_info *info,
+				      bfd *input_bfd, asection *input_section,
+				      Elf_Internal_Rela **rel,
+				      const Elf_Internal_Rela **relend,
+				      bfd_boolean rel_reloc,
+				      reloc_howto_type *howto,
+				      bfd_byte *contents)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
+  int count = bed->s->int_rels_per_ext_rel;
+  unsigned int r_type;
+  int i;
+
+  for (i = count - 1; i > 0; i--)
+    {
+      r_type = ELF_R_TYPE (output_bfd, (*rel)[i].r_info);
+      if (r_type != R_MIPS_NONE)
+	{
+	  howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type, !rel_reloc);
+	  break;
+	}
+    }
+  do
+    {
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+					(*rel), count, (*relend),
+					howto, i, contents);
+    }
+  while (0);
+}
+
 /* Relocate a MIPS ELF section.  */
 
 bfd_boolean
@@ -9390,8 +9439,12 @@ _bfd_mips_elf_relocate_section (bfd *out
 	}
 
       if (sec != NULL && elf_discarded_section (sec))
-	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+	{
+	  mips_reloc_against_discarded_section (output_bfd, info, input_bfd,
+						input_section, &rel, &relend,
+						rel_reloc, howto, contents);
+	  continue;
+	}
 
       if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd))
 	{
Index: binutils/bfd/elfxx-sparc.c
===================================================================
--- binutils.orig/bfd/elfxx-sparc.c
+++ binutils/bfd/elfxx-sparc.c
@@ -2965,7 +2965,7 @@ _bfd_sparc_elf_relocate_section (bfd *ou
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;
Index: binutils/bfd/elfxx-tilegx.c
===================================================================
--- binutils.orig/bfd/elfxx-tilegx.c
+++ binutils/bfd/elfxx-tilegx.c
@@ -3142,7 +3142,7 @@ tilegx_elf_relocate_section (bfd *output
 
       if (sec != NULL && elf_discarded_section (sec))
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-					 rel, relend, howto, contents);
+					 rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
 	continue;



More information about the Binutils mailing list