This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: problems building with -Wl,-q on RHEL4


On Mon, Dec 13, 2004 at 05:28:42PM -0800, Janis Johnson wrote:
> When building eon, a C++ program from SPEC CPU2000, on RHEL4 with the
> fixed binutils using "-m64 -Wl,-q" I get several errors that start with
> "relocation truncated to fit: R_PPC64_REL24".  In the past I've always
> been able to work around that problem by using one of the options
> -mno-fp-in-toc, -mno-sum-in-toc, or -mminimal-toc, but none of those
> allow me to build eon with -Wl,-q on RHEL4.  The same problem exists in
> GCC mainline and in the gcc-3_4-rhl-branch of the GCC CVS tree.  This
> isn't caused by Alan's new ld patch, just exposed by it; both are

Actually, I reckon my ld patch isn't quite right.  The problem being
that .opd may have been edited which necessarily means the .opd relocs
will be edited too.  Thus re-reading the original .opd relocs won't give
correct results.  This is likely to happen with C++ when linkonce
sections are used.

After fixing that, I found that attempting to link eon hit a ld segfault
due to the toc editing code not adjusting the output reloc size.

Committed.

	* elf64-ppc.c (struct ppc64_elf_obj_tdata): Add opd_relocs.
	(opd_entry_value): Use opd_relocs if available.
	(ppc64_elf_relocate_section): Don't set reloc_done.  Instead
	copy .opd relocations to opd_relocs.
	(ppc64_elf_edit_toc): Set rel_hdr.sh_size after editing relocs.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.181
diff -u -p -r1.181 elf64-ppc.c
--- bfd/elf64-ppc.c	11 Dec 2004 03:56:43 -0000	1.181
+++ bfd/elf64-ppc.c	19 Dec 2004 23:08:35 -0000
@@ -2380,6 +2380,9 @@ struct ppc64_elf_obj_tdata
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tlsld_got;
+
+  /* A copy of relocs before they are modified for --emit-relocs.  */
+  Elf_Internal_Rela *opd_relocs;
 };
 
 #define ppc64_elf_tdata(bfd) \
@@ -4696,7 +4699,7 @@ opd_entry_value (asection *opd_sec,
 		 bfd_vma *code_off)
 {
   bfd *opd_bfd = opd_sec->owner;
-  Elf_Internal_Rela *relocs, *save_relocs = NULL;
+  Elf_Internal_Rela *relocs;
   Elf_Internal_Rela *lo, *hi, *look;
   bfd_vma val;
 
@@ -4726,17 +4729,12 @@ opd_entry_value (asection *opd_sec,
       return val;
     }
 
-  /* If the .opd relocs have been adjusted for output, then we need to
-     re-read the original relocs rather than use the cached ones.  */
-  if (opd_sec->reloc_done)
-    {
-      save_relocs = elf_section_data (opd_sec)->relocs;
-      elf_section_data (opd_sec)->relocs = NULL;
-    }
+  relocs = ppc64_elf_tdata (opd_bfd)->opd_relocs;
+  if (relocs == NULL)
+    relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
 
   /* Go find the opd reloc at the sym address.  */
-  lo = relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL,
-					   !opd_sec->reloc_done);
+  lo = relocs;
   BFD_ASSERT (lo != NULL);
   hi = lo + opd_sec->reloc_count - 1; /* ignore last reloc */
   val = (bfd_vma) -1;
@@ -4807,11 +4805,6 @@ opd_entry_value (asection *opd_sec,
 	}
     }
 
-  if (opd_sec->reloc_done)
-    {
-      elf_section_data (opd_sec)->relocs = save_relocs;
-      free (relocs);
-    }
   return val;
 }
 
@@ -6996,6 +6989,9 @@ ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_
 		++wrel;
 	      }
 	  toc->reloc_count = wrel - relstart;
+	  elf_section_data (toc)->rel_hdr.sh_size
+	    = toc->reloc_count * elf_section_data (toc)->rel_hdr.sh_entsize;
+	  BFD_ASSERT (elf_section_data (toc)->rel_hdr2 == NULL);
 
 	  /* Adjust addends for relocs against the toc section sym.  */
 	  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
@@ -10440,8 +10436,19 @@ ppc64_elf_relocate_section (bfd *output_
   /* If we're emitting relocations, then shortly after this function
      returns, reloc offsets and addends for this section will be
      adjusted.  Worse, reloc symbol indices will be for the output
-     file rather than the input.  Let opd_entry_value know.  */
-  input_section->reloc_done = info->emitrelocations;
+     file rather than the input.  Save a copy of the relocs for
+     opd_entry_value.  */
+  if (is_opd && info->emitrelocations)
+    {
+      bfd_size_type amt;
+      amt = input_section->reloc_count * sizeof (Elf_Internal_Rela);
+      rel = bfd_alloc (input_bfd, amt);
+      BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd_relocs == NULL);
+      ppc64_elf_tdata (input_bfd)->opd_relocs = rel;
+      if (rel == NULL)
+	return FALSE;
+      memcpy (rel, relocs, amt);
+    }
   return ret;
 }
 

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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