This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: problems building with -Wl,-q on RHEL4
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Cc: Janis Johnson <janis187 at us dot ibm dot com>, gsmith at us dot ibm dot com,Yaakov Yaari <YAARI at il dot ibm dot com>
- Date: Mon, 20 Dec 2004 09:55:34 +1030
- Subject: 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