This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Fix ld/418
On Sun, Oct 10, 2004 at 05:24:38PM +0930, Alan Modra wrote:
> Those who peruse this patch may notice a FIXME. I'll attack that later,
> probably by iterating over input sections using link_orders in
> bfd_elf_discard_info. This code might fail if someone writes a linker
> script that deliberately reorders eh_frame sections, or uses HJ's new
> --sort-section linker options.
Hmm, link_orders aren't set up when bfd_elf_discard_info is called. I
toyed with writing a linker function to traverse the script and call a
function on each input section mapped to a particular output section,
then decided it wasn't worth the bother.
* elf-bfd.h (struct eh_frame_hdr_info): Add offsets_adjusted.
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Adjust
offsets stored in struct eh_cie_fde entries before doing other
work.
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.160
diff -u -p -r1.160 elf-bfd.h
--- bfd/elf-bfd.h 10 Oct 2004 07:58:07 -0000 1.160
+++ bfd/elf-bfd.h 10 Oct 2004 12:47:40 -0000
@@ -328,6 +328,7 @@ struct eh_frame_hdr_info
We build it if we successfully read all .eh_frame input sections
and recognize them. */
bfd_boolean table;
+ bfd_boolean offsets_adjusted;
};
/* ELF linker hash table. */
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.33
diff -u -p -r1.33 elf-eh-frame.c
--- bfd/elf-eh-frame.c 10 Oct 2004 07:58:07 -0000 1.33
+++ bfd/elf-eh-frame.c 10 Oct 2004 12:47:40 -0000
@@ -798,6 +798,39 @@ _bfd_elf_write_section_eh_frame (bfd *ab
sec_info = elf_section_data (sec)->sec_info;
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
+
+ /* First convert all offsets to output section offsets, so that a
+ CIE offset is valid if the CIE is used by a FDE from some other
+ section. This can happen when duplicate CIEs are deleted in
+ _bfd_elf_discard_section_eh_frame. We do all sections here because
+ this function might not be called on sections in the same order as
+ _bfd_elf_discard_section_eh_frame. */
+ if (!hdr_info->offsets_adjusted)
+ {
+ bfd *ibfd;
+ asection *eh;
+ struct eh_frame_sec_info *eh_inf;
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ {
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || (ibfd->flags & DYNAMIC) != 0)
+ continue;
+
+ eh = bfd_get_section_by_name (ibfd, ".eh_frame");
+ if (eh == NULL || eh->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
+ continue;
+
+ eh_inf = elf_section_data (eh)->sec_info;
+ for (ent = eh_inf->entry; ent < eh_inf->entry + eh_inf->count; ++ent)
+ {
+ ent->offset += eh->output_offset;
+ ent->new_offset += eh->output_offset;
+ }
+ }
+ hdr_info->offsets_adjusted = TRUE;
+ }
+
if (hdr_info->table && hdr_info->array == NULL)
hdr_info->array
= bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
@@ -810,16 +843,6 @@ _bfd_elf_write_section_eh_frame (bfd *ab
if (ent->removed)
continue;
- /* First convert all offsets to output section offsets, so that a
- CIE offset is valid if the CIE is used by a FDE from some other
- section. This can happen when duplicate CIEs are deleted in
- _bfd_elf_discard_section_eh_frame.
- FIXME: This assumes that _bfd_elf_discard_section_eh_frame is
- called on sections in the same order as this function, which
- isn't necessarily so. */
- ent->offset += sec->output_offset;
- ent->new_offset += sec->output_offset;
-
if (ent->cie)
{
/* CIE */
--
Alan Modra
IBM OzLabs - Linux Technology Centre