summaryrefslogtreecommitdiff
path: root/bfd/elf-eh-frame.c
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2007-12-15 09:34:48 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2007-12-15 09:34:48 +0000
commit9d0a14d3f3339d988a395262538629b05cac99d3 (patch)
treef98722f3a58a6f0ddeee68b430e162cb6e778c8c /bfd/elf-eh-frame.c
parentca92cecbbead0c883df57e70fdb5b2541febd43b (diff)
downloadbinutils-gdb-9d0a14d3f3339d988a395262538629b05cac99d3.tar.gz
bfd/
* elf-bfd.h (eh_cie_fde): Add u.fde.next_for_section and u.cie.gc_mark. (bfd_elf_section_data): Add fde_list. (elf_fde_list): New macro. (elf_obj_tdata): Add eh_frame_section. (elf_eh_frame_section): New macro. (_bfd_elf_gc_mark_reloc): Remove last parameter. (_bfd_elf_gc_mark_fdes): Declare. * elf-eh-frame.c (_bfd_elf_get_eh_frame_sec_info): Chain the FDEs for each input section. (mark_entry, _bfd_elf_gc_mark_fdes): New functions. * elflink.c (_bfd_elf_gc_mark_reloc): Remove is_eh parameter. (_bfd_elf_gc_mark): Update call accordingly. Mark the relocations againts the section's FDEs. Don't mark the bfd's elf_eh_frame_section. (bfd_elf_gc_sections): Parse each input bfd's .eh_frame before marking any input sections. Remove the current EH handling. * section.c (bfd_section): Remove gc_mark_from_eh. * ecoff.c (bfd_debug_section): Update initializer accordingly.
Diffstat (limited to 'bfd/elf-eh-frame.c')
-rw-r--r--bfd/elf-eh-frame.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 63b6ba45f94..460112c8a6f 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -475,6 +475,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
unsigned int ptr_size;
unsigned int num_cies;
unsigned int num_entries;
+ elf_gc_mark_hook_fn gc_mark_hook;
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
@@ -577,6 +578,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
buf = ehbuf;
ecie_count = 0;
+ gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
while ((bfd_size_type) (buf - ehbuf) != sec->size)
{
char *aug;
@@ -821,6 +823,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
}
else
{
+ asection *rsec;
+
/* Find the corresponding CIE. */
unsigned int cie_offset = this_inf->offset + 4 - hdr_id;
for (ecie = ecies; ecie < ecies + ecie_count; ++ecie)
@@ -836,6 +840,12 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
ENSURE_NO_RELOCS (buf);
REQUIRE (GET_RELOC (buf));
+ /* Chain together the FDEs for each section. */
+ rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
+ REQUIRE (rsec && rsec->owner == abfd);
+ this_inf->u.fde.next_for_section = elf_fde_list (rsec);
+ elf_fde_list (rsec) = this_inf;
+
/* Skip the initial location and address range. */
start = buf;
length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
@@ -976,6 +986,55 @@ _bfd_elf_end_eh_frame_parsing (struct bfd_link_info *info)
hdr_info->parsed_eh_frames = TRUE;
}
+/* Mark all relocations against CIE or FDE ENT, which occurs in
+ .eh_frame section SEC. COOKIE describes the relocations in SEC;
+ its "rel" field can be changed freely. */
+
+static bfd_boolean
+mark_entry (struct bfd_link_info *info, asection *sec,
+ struct eh_cie_fde *ent, elf_gc_mark_hook_fn gc_mark_hook,
+ struct elf_reloc_cookie *cookie)
+{
+ for (cookie->rel = cookie->rels + ent->reloc_index;
+ cookie->rel < cookie->relend
+ && cookie->rel->r_offset < ent->offset + ent->size;
+ cookie->rel++)
+ if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, cookie))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Mark all the relocations against FDEs that relate to code in input
+ section SEC. The FDEs belong to .eh_frame section EH_FRAME, whose
+ relocations are described by COOKIE. */
+
+bfd_boolean
+_bfd_elf_gc_mark_fdes (struct bfd_link_info *info, asection *sec,
+ asection *eh_frame, elf_gc_mark_hook_fn gc_mark_hook,
+ struct elf_reloc_cookie *cookie)
+{
+ struct eh_cie_fde *fde, *cie, *merged;
+
+ for (fde = elf_fde_list (sec); fde; fde = fde->u.fde.next_for_section)
+ {
+ if (!mark_entry (info, eh_frame, fde, gc_mark_hook, cookie))
+ return FALSE;
+
+ /* At this stage, all cie_inf fields point to local CIEs, so we
+ can use the same cookie to refer to them. */
+ cie = fde->u.fde.cie_inf;
+ merged = cie->u.cie.merged;
+ if (!merged->u.cie.gc_mark)
+ {
+ merged->u.cie.gc_mark = 1;
+ if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/* This function is called for each input file before the .eh_frame
section is relocated. It discards duplicate CIEs and FDEs for discarded
functions. The function returns TRUE iff any entries have been