aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf-eh-frame.c57
3 files changed, 47 insertions, 18 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 623eefa..634591d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,10 @@
2004-10-10 Alan Modra <amodra@bigpond.net.au>
+ * 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.
+
* elf-bfd.h (struct eh_cie_fde): Add cie_inf, remove sec.
(struct eh_frame_hdr_info): Add last_cie_inf, remove last_cie_offset.
* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Delete code
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index f9b1b4a..f452d3b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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. */
@@ -1259,7 +1260,7 @@ struct elf_obj_tdata
unsigned int cverrefs;
/* Segment flags for the PT_GNU_STACK segment. */
- unsigned int stack_flags;
+ unsigned int stack_flags;
/* Should the PT_GNU_RELRO segment be emitted? */
bfd_boolean relro;
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 9bc5ea4..6302cf0 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -234,7 +234,7 @@ _bfd_elf_discard_section_eh_frame
&& bfd_is_abs_section (sec->output_section)))
{
/* At least one of the sections is being discarded from the
- link, so we should just ignore them. */
+ link, so we should just ignore them. */
return FALSE;
}
@@ -284,14 +284,14 @@ _bfd_elf_discard_section_eh_frame
#define SKIP_RELOCS(buf) \
while (cookie->rel < cookie->relend \
- && (cookie->rel->r_offset \
+ && (cookie->rel->r_offset \
< (bfd_size_type) ((buf) - ehbuf))) \
cookie->rel++
#define GET_RELOC(buf) \
((cookie->rel < cookie->relend \
&& (cookie->rel->r_offset \
- == (bfd_size_type) ((buf) - ehbuf))) \
+ == (bfd_size_type) ((buf) - ehbuf))) \
? cookie->rel : NULL)
for (;;)
@@ -511,7 +511,7 @@ _bfd_elf_discard_section_eh_frame
/* For shared libraries, try to get rid of as many RELATIVE relocs
as possible. */
- if (info->shared
+ if (info->shared
&& (get_elf_backend_data (abfd)
->elf_backend_can_make_relative_eh_frame
(abfd, info, sec))
@@ -798,6 +798,39 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
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 *abfd,
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 */
@@ -864,7 +887,7 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
break;
case 'P':
per_encoding = *buf++;
- per_width = get_DW_EH_PE_width (per_encoding, ptr_size);
+ per_width = get_DW_EH_PE_width (per_encoding, ptr_size);
BFD_ASSERT (per_width != 0);
BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)
== ent->per_encoding_relative);
@@ -1013,8 +1036,8 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
BFD_ASSERT ((bfd_size_type) (p - contents) == sec->size);
return bfd_set_section_contents (abfd, sec->output_section,
- contents, (file_ptr) sec->output_offset,
- sec->size);
+ contents, (file_ptr) sec->output_offset,
+ sec->size);
}
/* Helper function used to sort .eh_frame_hdr search table by increasing