+ else
+ {
+ Elf_Internal_Sym *sym;
+ asection *sym_sec;
+
+ sym = &cookie->locsyms[r_symndx];
+ sym_sec = bfd_section_from_elf_index (abfd, sym->st_shndx);
+ if (sym_sec == NULL)
+ return cie_inf;
+
+ if (sym_sec->kept_section != NULL)
+ sym_sec = sym_sec->kept_section;
+ if (sym_sec->output_section == NULL)
+ return cie_inf;
+
+ cie->local_personality = 1;
+ cie->personality.sym.bfd_id = abfd->id;
+ cie->personality.sym.index = r_symndx;
+ per_binds_local = TRUE;
+ }
+
+ if (per_binds_local
+ && bfd_link_pic (info)
+ && (cie->per_encoding & 0x70) == DW_EH_PE_absptr
+ && (get_elf_backend_data (abfd)
+ ->elf_backend_can_make_relative_eh_frame (abfd, info, sec)))
+ {
+ cie_inf->u.cie.make_per_encoding_relative = 1;
+ cie_inf->u.cie.per_encoding_relative = 1;
+ }
+ }
+
+ /* See if we can merge this CIE with an earlier one. */
+ cie_compute_hash (cie);
+ if (hdr_info->u.dwarf.cies == NULL)
+ {
+ hdr_info->u.dwarf.cies = htab_try_create (1, cie_hash, cie_eq, free);
+ if (hdr_info->u.dwarf.cies == NULL)
+ return cie_inf;
+ }
+ loc = htab_find_slot_with_hash (hdr_info->u.dwarf.cies, cie,
+ cie->hash, INSERT);
+ if (loc == NULL)
+ return cie_inf;
+
+ new_cie = (struct cie *) *loc;
+ if (new_cie == NULL)
+ {
+ /* Keep CIE_INF and record it in the hash table. */
+ new_cie = (struct cie *) malloc (sizeof (struct cie));
+ if (new_cie == NULL)
+ return cie_inf;
+
+ memcpy (new_cie, cie, sizeof (struct cie));
+ *loc = new_cie;
+ }
+ else
+ {
+ /* Merge CIE_INF with NEW_CIE->CIE_INF. */
+ cie_inf->removed = 1;
+ cie_inf->u.cie.merged = 1;
+ cie_inf->u.cie.u.merged_with = new_cie->cie_inf;
+ if (cie_inf->u.cie.make_lsda_relative)
+ new_cie->cie_inf->u.cie.make_lsda_relative = 1;
+ }
+ return new_cie->cie_inf;
+}
+
+/* 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
+ deleted. */
+
+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, eh_alignment;
+
+ 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 && ent->u.fde.cie_inf != NULL)
+ {
+ 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 (bfd_link_pic (info)
+ && (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr
+ && ent->make_relative == 0)
+ || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned))
+ {
+ static int num_warnings_issued = 0;
+
+ /* 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->u.dwarf.table = FALSE;
+ if (num_warnings_issued < 10)
+ {
+ (*info->callbacks->einfo)
+ /* xgettext:c-format */
+ (_("%P: FDE encoding in %B(%A) prevents .eh_frame_hdr"
+ " table being created.\n"), abfd, sec);
+ num_warnings_issued ++;
+ }
+ else if (num_warnings_issued == 10)
+ {
+ (*info->callbacks->einfo)
+ (_("%P: Further warnings about FDE encoding preventing .eh_frame_hdr generation dropped.\n"));
+ num_warnings_issued ++;
+ }
+ }
+ ent->removed = 0;
+ hdr_info->u.dwarf.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;