+bfd_boolean
+_bfd_elf_discard_section_eh_frame
+ (bfd *abfd, struct bfd_link_info *info, asection *sec,
+ bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
+ struct elf_reloc_cookie *cookie)
+{
+ struct eh_cie_fde *ent;
+ struct eh_frame_sec_info *sec_info;
+ struct eh_frame_hdr_info *hdr_info;
+ unsigned int ptr_size, offset;
+
+ if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME)
+ return FALSE;
+
+ sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info;
+ if (sec_info == NULL)
+ return FALSE;
+
+ ptr_size = (get_elf_backend_data (sec->owner)
+ ->elf_backend_eh_frame_address_size (sec->owner, sec));
+
+ hdr_info = &elf_hash_table (info)->eh_info;
+ for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
+ if (ent->size == 4)
+ /* There should only be one zero terminator, on the last input
+ file supplying .eh_frame (crtend.o). Remove any others. */
+ ent->removed = sec->map_head.s != NULL;
+ else if (!ent->cie)
+ {
+ bfd_boolean keep;
+ if ((sec->flags & SEC_LINKER_CREATED) != 0 && cookie->rels == NULL)
+ {
+ unsigned int width
+ = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
+ bfd_vma value
+ = read_value (abfd, sec->contents + ent->offset + 8 + width,
+ width, get_DW_EH_PE_signed (ent->fde_encoding));
+ keep = value != 0;
+ }
+ else
+ {
+ cookie->rel = cookie->rels + ent->reloc_index;
+ /* FIXME: octets_per_byte. */
+ BFD_ASSERT (cookie->rel < cookie->relend
+ && cookie->rel->r_offset == ent->offset + 8);
+ keep = !(*reloc_symbol_deleted_p) (ent->offset + 8, cookie);
+ }
+ if (keep)
+ {
+ if (info->shared
+ && (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr
+ && ent->make_relative == 0)
+ || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned))
+ {
+ /* If a shared library uses absolute pointers
+ which we cannot turn into PC relative,
+ don't create the binary search table,
+ since it is affected by runtime relocations. */
+ hdr_info->table = FALSE;
+ (*info->callbacks->einfo)
+ (_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr"
+ " table being created.\n"), abfd, sec);
+ }
+ ent->removed = 0;
+ hdr_info->fde_count++;
+ ent->u.fde.cie_inf = find_merged_cie (abfd, info, sec, hdr_info,
+ cookie, ent->u.fde.cie_inf);
+ }
+ }
+
+ if (sec_info->cies)
+ {
+ free (sec_info->cies);
+ sec_info->cies = NULL;
+ }
+
+ offset = 0;
+ for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
+ if (!ent->removed)
+ {
+ ent->new_offset = offset;
+ offset += size_of_output_cie_fde (ent, ptr_size);
+ }
+
+ sec->rawsize = sec->size;
+ sec->size = offset;
+ return offset != sec->rawsize;