static bfd_boolean _bfd_elf_fix_symbol_flags
(struct elf_link_hash_entry *, struct elf_info_failed *);
+asection *
+_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
+ unsigned long r_symndx,
+ bfd_boolean discard)
+{
+ if (r_symndx >= cookie->locsymcount
+ || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
+
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && discarded_section (h->root.u.def.section))
+ return h->root.u.def.section;
+ else
+ return NULL;
+ }
+ else
+ {
+ /* It's not a relocation against a global symbol,
+ but it could be a relocation against a local
+ symbol for a discarded section. */
+ asection *isec;
+ Elf_Internal_Sym *isym;
+
+ /* Need to: get the symbol; get the section. */
+ isym = &cookie->locsyms[r_symndx];
+ isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx);
+ if (isec != NULL
+ && discard ? discarded_section (isec) : 1)
+ return isec;
+ }
+ return NULL;
+}
+
/* Define a symbol in a dynamic linkage section. */
struct elf_link_hash_entry *
/* No error if extern_protected_data is true. */
if (h->protected_def
- && !get_elf_backend_data (dynbss->owner)->extern_protected_data)
+ && (!info->extern_protected_data
+ || (info->extern_protected_data < 0
+ && !get_elf_backend_data (dynbss->owner)->extern_protected_data)))
info->callbacks->einfo
(_("%P: copy reloc against protected `%T' is dangerous\n"),
h->root.root.string);
/* If extern_protected_data is false, STV_PROTECTED non-function
symbols are local. */
- if (!bed->extern_protected_data && !bed->is_function_type (h->type))
+ if ((!info->extern_protected_data
+ || (info->extern_protected_data < 0
+ && !bed->extern_protected_data))
+ && !bed->is_function_type (h->type))
return TRUE;
/* Function pointer equality tests may require that STV_PROTECTED
{
case SEC_INFO_TYPE_STABS:
case SEC_INFO_TYPE_EH_FRAME:
+ case SEC_INFO_TYPE_EH_FRAME_ENTRY:
return TRUE;
default:
break;
return FALSE;
}
break;
+ case SEC_INFO_TYPE_EH_FRAME_ENTRY:
+ {
+ if (! _bfd_elf_write_section_eh_frame_entry (output_bfd,
+ flinfo->info,
+ o, contents))
+ return FALSE;
+ }
+ break;
default:
{
/* FIXME: octets_per_byte. */
to count upwards while actually outputting the relocations. */
esdo->rel.count = 0;
esdo->rela.count = 0;
+
+ if (esdo->this_hdr.sh_offset == (file_ptr) -1)
+ {
+ /* Cache the section contents so that they can be compressed
+ later. Use bfd_malloc since it will be freed by
+ bfd_compress_section_contents. */
+ unsigned char *contents = esdo->this_hdr.contents;
+ if ((o->flags & SEC_ELF_COMPRESS) == 0 || contents != NULL)
+ abort ();
+ contents
+ = (unsigned char *) bfd_malloc (esdo->this_hdr.sh_size);
+ if (contents == NULL)
+ goto error_return;
+ esdo->this_hdr.contents = contents;
+ }
}
/* We have now assigned file positions for all the sections except
return FALSE;
}
+ if (!_bfd_elf_fixup_eh_frame_hdr (info))
+ return FALSE;
+
/* Since ELF permits relocations to be against local symbols, we
must have the local symbols available when we do the relocations.
Since we would rather only read the local symbols once, and we
}
}
+ eh_frame = elf_section_eh_frame_entry (sec);
+ if (ret && eh_frame && !eh_frame->gc_mark)
+ if (!_bfd_elf_gc_mark (info, eh_frame, gc_mark_hook))
+ ret = FALSE;
+
return ret;
}
}
}
+bfd_boolean
+bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
+{
+ bfd *ibfd = info->input_bfds;
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
+ {
+ asection *sec;
+ struct elf_reloc_cookie cookie;
+
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ continue;
+
+ if (!init_reloc_cookie (&cookie, info, ibfd))
+ return FALSE;
+
+ for (sec = ibfd->sections; sec; sec = sec->next)
+ {
+ if (CONST_STRNEQ (bfd_section_name (ibfd, sec), ".eh_frame_entry")
+ && init_reloc_cookie_rels (&cookie, info, ibfd, sec))
+ {
+ _bfd_elf_parse_eh_frame_entry (info, sec, &cookie);
+ fini_reloc_cookie_rels (&cookie, sec);
+ }
+ }
+ }
+ return TRUE;
+}
+
/* Do mark and sweep of unused sections. */
bfd_boolean
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section
at the .eh_frame section if we can mark the FDEs individually. */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+ for (sub = info->input_bfds;
+ info->eh_frame_hdr_type != COMPACT_EH_HDR && sub != NULL;
+ sub = sub->link.next)
{
asection *sec;
struct elf_reloc_cookie cookie;
}
}
- o = bfd_get_section_by_name (output_bfd, ".eh_frame");
+ o = NULL;
+ if (info->eh_frame_hdr_type != COMPACT_EH_HDR)
+ o = bfd_get_section_by_name (output_bfd, ".eh_frame");
if (o != NULL)
{
asection *i;
}
}
- if (info->eh_frame_hdr
+ if (info->eh_frame_hdr_type == COMPACT_EH_HDR)
+ _bfd_elf_end_eh_frame_parsing (info);
+
+ if (info->eh_frame_hdr_type
&& !info->relocatable
&& _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
changed = 1;