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 *
static void
elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
- const Elf_Internal_Sym *isym,
+ const Elf_Internal_Sym *isym, asection *sec,
bfd_boolean definition, bfd_boolean dynamic)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (symvis - 1 < hvis - 1)
h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1));
}
- else if (definition && ELF_ST_VISIBILITY (isym->st_other) != STV_DEFAULT)
+ else if (definition
+ && ELF_ST_VISIBILITY (isym->st_other) != STV_DEFAULT
+ && (sec->flags & SEC_READONLY) == 0)
h->protected_def = 1;
}
/* Merge st_other. If the symbol already has a dynamic index,
but visibility says it should not be visible, turn it into a
local symbol. */
- elf_merge_st_other (abfd, h, sym, newdef, newdyn);
+ elf_merge_st_other (abfd, h, sym, sec, newdef, newdyn);
if (h->dynindx != -1)
switch (ELF_ST_VISIBILITY (h->other))
{
/* No error if extern_protected_data is true. */
if (h->protected_def
- && !get_elf_backend_data (dynbss->owner)->extern_protected_data)
- {
- info->callbacks->einfo
- (_("%P: copy reloc against protected `%T' is invalid\n"),
- h->root.root.string);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
+ && (!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);
return TRUE;
}
/* 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
if (abfd == NULL)
return FALSE;
+ /* Return FALSE if the object has been claimed by plugin. */
+ if (abfd->plugin_format == bfd_plugin_yes)
+ return FALSE;
+
if (! bfd_check_format (abfd, bfd_object))
return FALSE;
}
/* Merge st_other field. */
- elf_merge_st_other (abfd, h, isym, definition, dynamic);
+ elf_merge_st_other (abfd, h, isym, sec, definition, dynamic);
/* We don't want to make debug symbol dynamic. */
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
break;
case 4:
bfd_put_32 (input_bfd, x, location);
- x >>= 32;
+ /* Computed this way because x >>= 32 is undefined if x is a 32-bit value. */
+ x >>= 16;
+ x >>= 16;
break;
#ifdef BFD64
case 8:
{
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;
}
isec->name, ilen) == 0)
{
dsec->gc_mark = 0;
- break;
}
}
}
{
asection *o;
- if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+ if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+ || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
continue;
for (o = sub->sections; o != NULL; o = o->next)
}
}
+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;
{
asection *o;
- if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+ if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+ || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
continue;
/* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep).
}
}
- 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;
ehdest->target_internal = ehsrc->target_internal;
isym.st_other = ehsrc->other;
- elf_merge_st_other (abfd, ehdest, &isym, TRUE, FALSE);
+ elf_merge_st_other (abfd, ehdest, &isym, NULL, TRUE, FALSE);
}
/* Append a RELA relocation REL to section S in BFD. */