}
}
-/* Mark if a symbol has a definition in a dynamic object or is
- weak in all dynamic objects. */
-
-static void
-_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
- asection *sec, int bind)
-{
- if (!h->dynamic_def)
- {
- if (!bfd_is_und_section (sec))
- h->dynamic_def = 1;
- else
- {
- /* Check if this symbol is weak in all dynamic objects. If it
- is the first time we see it in a dynamic object, we mark
- if it is weak. Otherwise, we clear it. */
- if (!h->ref_dynamic)
- {
- if (bind == STB_WEAK)
- h->dynamic_weak = 1;
- }
- else if (bind != STB_WEAK)
- h->dynamic_weak = 0;
- }
- }
-}
-
/* This function is called when we want to define a new symbol. It
handles the various cases which arise when we find a definition in
a dynamic object, or when there is already a definition in a
h = (struct elf_link_hash_entry *) h->root.u.i.link;
/* We have to check it for every instance since the first few may be
- refereences and not all compilers emit symbol type for undefined
+ references and not all compilers emit symbol type for undefined
symbols. */
bfd_elf_link_mark_dynamic_symbol (info, h, sym);
+ /* NEWDYN and OLDDYN indicate whether the new or old symbol,
+ respectively, is from a dynamic object. */
+
+ newdyn = (abfd->flags & DYNAMIC) != 0;
+
+ /* ref_dynamic_nonweak and dynamic_def flags track actual undefined
+ syms and defined syms in dynamic libraries respectively.
+ ref_dynamic on the other hand can be set for a symbol defined in
+ a dynamic library, and def_dynamic may not be set; When the
+ definition in a dynamic lib is overridden by a definition in the
+ executable use of the symbol in the dynamic lib becomes a
+ reference to the executable symbol. */
+ if (newdyn)
+ {
+ if (bfd_is_und_section (sec))
+ {
+ if (bind != STB_WEAK)
+ {
+ h->ref_dynamic_nonweak = 1;
+ hi->ref_dynamic_nonweak = 1;
+ }
+ }
+ else
+ {
+ h->dynamic_def = 1;
+ hi->dynamic_def = 1;
+ }
+ }
+
/* If we just created the symbol, mark it as being an ELF symbol.
Other than that, there is nothing to do--there is no merge issue
with a newly defined symbol--so we just return. */
|| !h->def_regular))
return TRUE;
- /* NEWDYN and OLDDYN indicate whether the new or old symbol,
- respectively, is from a dynamic object. */
-
- newdyn = (abfd->flags & DYNAMIC) != 0;
-
olddyn = FALSE;
if (oldbfd != NULL)
olddyn = (oldbfd->flags & DYNAMIC) != 0;
return FALSE;
}
- /* We need to remember if a symbol has a definition in a dynamic
- object or is weak in all dynamic objects. Internal and hidden
- visibility will make it unavailable to dynamic objects. */
- if (newdyn)
- {
- _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
- if (h != hi)
- _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
- }
-
/* If the old symbol has non-default visibility, we ignore the new
definition from a dynamic object. */
if (newdyn
h->ref_dynamic = 1;
h->def_dynamic = 0;
- h->dynamic_def = 0;
/* FIXME: Should we check type and size for protected symbol? */
h->size = 0;
h->type = 0;
else
h->ref_dynamic = 1;
h->def_dynamic = 0;
- h->dynamic_def = 0;
/* FIXME: Should we check type and size for protected symbol? */
h->size = 0;
h->type = 0;
return TRUE;
}
- if (bind == STB_GNU_UNIQUE)
- h->unique_global = 1;
-
/* If a new weak symbol definition comes from a regular file and the
old symbol comes from a dynamic library, we treat the new one as
strong. Similarly, an old weak symbol definition from a regular
&& !h->def_regular
&& h->ref_regular
&& !h->def_dynamic
- && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+ && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
h->def_regular = 1;
/* If -Bsymbolic was used (which means to bind references to global
bfd_boolean skip;
/* If this is a definition of a symbol which was previously
- referenced in a non-weak manner then make a note of the bfd
- that contained the reference. This is used if we need to
- refer to the source of the reference later on. */
+ referenced, then make a note of the bfd that contained the
+ reference. This is used if we need to refer to the source
+ of the reference later on. */
if (! bfd_is_und_section (sec))
{
- h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+ h = elf_link_hash_lookup (elf_hash_table (info), name,
+ FALSE, FALSE, FALSE);
if (h != NULL
- && h->root.type == bfd_link_hash_undefined
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
&& h->root.u.undef.abfd)
undef_bfd = h->root.u.undef.abfd;
}
}
/* If necessary, make a second attempt to locate the bfd
- containing an unresolved, non-weak reference to the
- current symbol. */
+ containing an unresolved reference to the current symbol. */
if (! bfd_is_und_section (sec) && undef_bfd == NULL)
{
- h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+ h = elf_link_hash_lookup (elf_hash_table (info), name,
+ FALSE, FALSE, FALSE);
if (h != NULL
- && h->root.type == bfd_link_hash_undefined
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
&& h->root.u.undef.abfd)
undef_bfd = h->root.u.undef.abfd;
}
}
if (elf_tdata (abfd)->verdef != NULL
- && ! override
&& vernum > 1
&& definition)
h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
h = (struct elf_link_hash_entry *) h->root.u.i.link;
*sym_hash = h;
- if (is_elf_hash_table (htab))
- h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
new_weak = (flags & BSF_WEAK) != 0;
new_weakdef = FALSE;
is one which is referenced or defined by both a regular
object and a shared object. */
dynsym = FALSE;
- if (! dynamic)
+
+ /* Plugin symbols aren't normal. Don't set def_regular or
+ ref_regular for them, nor make them dynamic. */
+ if ((abfd->flags & BFD_PLUGIN) != 0)
+ ;
+ else if (! dynamic)
{
if (! definition)
{
else
{
h->def_dynamic = 1;
- h->dynamic_def = 1;
hi->def_dynamic = 1;
- hi->dynamic_def = 1;
}
/* If the indirect symbol has been forced local, don't
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
dynsym = FALSE;
- /* Nor should we make plugin symbols dynamic. */
- if ((abfd->flags & BFD_PLUGIN) != 0)
- dynsym = FALSE;
-
if (definition)
- h->target_internal = isym->st_target_internal;
+ {
+ h->target_internal = isym->st_target_internal;
+ h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
+ }
/* Check to see if we need to add an indirect symbol for
the default name. */
break;
}
+ /* Don't add DT_NEEDED for references from the dummy bfd. */
if (!add_needed
&& definition
&& ((dynsym
- && h->ref_regular)
- || (h->ref_dynamic
+ && h->ref_regular_nonweak
+ && (undef_bfd == NULL
+ || (undef_bfd->flags & BFD_PLUGIN) == 0))
+ || (h->ref_dynamic_nonweak
&& (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
&& !on_needed_list (elf_dt_name (abfd), htab->needed))))
{
--no-add-needed is used and the reference was not
a weak one. */
if (undef_bfd != NULL
+ && h->ref_regular_nonweak
&& (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
{
(*_bfd_error_handler)
memcpy (sym_hash, old_hash, hashsize);
htab->root.undefs = old_undefs;
htab->root.undefs_tail = old_undefs_tail;
- _bfd_elf_strtab_clear_refs (htab->dynstr, old_dynstr_size);
+ _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
for (i = 0; i < htab->root.table.size; i++)
{
struct bfd_hash_entry *p;
/* Determine any GNU_STACK segment requirements, after the backend
has had a chance to set a default segment size. */
if (info->execstack)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
+ elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
else if (info->noexecstack)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
+ elf_stack_flags (output_bfd) = PF_R | PF_W;
else
{
bfd *inputobj;
exec = PF_X;
}
if (notesec || info->stacksize > 0)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
+ elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
if (notesec && exec && info->relocatable
&& notesec->output_section != bfd_abs_section_ptr)
notesec->output_section->flags |= SEC_CODE;
if (rpath != NULL)
{
bfd_size_type indx;
+ bfd_vma tag;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
TRUE);
- if (indx == (bfd_size_type) -1
- || !_bfd_elf_add_dynamic_entry (info, DT_RPATH, indx))
+ if (indx == (bfd_size_type) -1)
return FALSE;
- if (info->new_dtags)
- {
- _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
- if (!_bfd_elf_add_dynamic_entry (info, DT_RUNPATH, indx))
- return FALSE;
- }
+ tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
+ if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
+ return FALSE;
}
if (filter_shlib != NULL)
}
}
-/* Initialize an ELF linker hash table. */
+/* Initialize an ELF linker hash table. *TABLE has been zeroed by our
+ caller. */
bfd_boolean
_bfd_elf_link_hash_table_init
bfd_boolean ret;
int can_refcount = get_elf_backend_data (abfd)->can_refcount;
- memset (table, 0, sizeof * table);
table->init_got_refcount.refcount = can_refcount - 1;
table->init_plt_refcount.refcount = can_refcount - 1;
table->init_got_offset.offset = -(bfd_vma) 1;
struct elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_link_hash_table);
- ret = (struct elf_link_hash_table *) bfd_malloc (amt);
+ ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
return &ret->root;
}
+/* Destroy an ELF linker hash table. */
+
+void
+_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+{
+ struct elf_link_hash_table *htab = (struct elf_link_hash_table *) hash;
+ if (htab->dynstr != NULL)
+ _bfd_elf_strtab_free (htab->dynstr);
+ _bfd_merge_sections_free (htab->merge_info);
+ _bfd_generic_link_hash_table_free (hash);
+}
+
/* This is a hook for the ELF emulation code in the generic linker to
tell the backend linker what file name to use for the DT_NEEDED
entry for a dynamic object. */
&& h->ref_dynamic
&& h->def_regular
&& !h->dynamic_def
- && !h->dynamic_weak
+ && h->ref_dynamic_nonweak
&& !elf_link_check_versioned_symbol (flinfo->info, bed, h))
{
bfd *def_bfd;
/* Turn off visibility on local symbol. */
sym.st_other &= ~ELF_ST_VISIBILITY (-1);
}
- else if (h->unique_global)
+ /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */
+ else if (h->unique_global && h->def_regular)
sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
else if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak)
return TRUE;
}
+static void
+elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
+{
+ asection *o;
+
+ if (flinfo->symstrtab != NULL)
+ _bfd_stringtab_free (flinfo->symstrtab);
+ if (flinfo->contents != NULL)
+ free (flinfo->contents);
+ if (flinfo->external_relocs != NULL)
+ free (flinfo->external_relocs);
+ if (flinfo->internal_relocs != NULL)
+ free (flinfo->internal_relocs);
+ if (flinfo->external_syms != NULL)
+ free (flinfo->external_syms);
+ if (flinfo->locsym_shndx != NULL)
+ free (flinfo->locsym_shndx);
+ if (flinfo->internal_syms != NULL)
+ free (flinfo->internal_syms);
+ if (flinfo->indices != NULL)
+ free (flinfo->indices);
+ if (flinfo->sections != NULL)
+ free (flinfo->sections);
+ if (flinfo->symbuf != NULL)
+ free (flinfo->symbuf);
+ if (flinfo->symshndxbuf != NULL)
+ free (flinfo->symshndxbuf);
+ for (o = obfd->sections; o != NULL; o = o->next)
+ {
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
+ free (esdo->rel.hashes);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
+ free (esdo->rela.hashes);
+ }
+}
/* Do the final step of an ELF link. */
/* sh_offset is set just below. */
symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
- off = elf_tdata (abfd)->next_file_pos;
+ off = elf_next_file_pos (abfd);
off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
- /* Note that at this point elf_tdata (abfd)->next_file_pos is
+ /* Note that at this point elf_next_file_pos (abfd) is
incorrect. We do not yet know the size of the .symtab section.
We correct next_file_pos below, after we do know the size. */
symstrtab_hdr->sh_addralign = 1;
off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE);
- elf_tdata (abfd)->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
if (bfd_get_symcount (abfd) > 0)
{
goto error_return;
}
- if (info->eh_frame_hdr)
- {
- if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
- goto error_return;
- }
+ if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+ goto error_return;
- if (flinfo.symstrtab != NULL)
- _bfd_stringtab_free (flinfo.symstrtab);
- if (flinfo.contents != NULL)
- free (flinfo.contents);
- if (flinfo.external_relocs != NULL)
- free (flinfo.external_relocs);
- if (flinfo.internal_relocs != NULL)
- free (flinfo.internal_relocs);
- if (flinfo.external_syms != NULL)
- free (flinfo.external_syms);
- if (flinfo.locsym_shndx != NULL)
- free (flinfo.locsym_shndx);
- if (flinfo.internal_syms != NULL)
- free (flinfo.internal_syms);
- if (flinfo.indices != NULL)
- free (flinfo.indices);
- if (flinfo.sections != NULL)
- free (flinfo.sections);
- if (flinfo.symbuf != NULL)
- free (flinfo.symbuf);
- if (flinfo.symshndxbuf != NULL)
- free (flinfo.symshndxbuf);
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- struct bfd_elf_section_data *esdo = elf_section_data (o);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
- free (esdo->rel.hashes);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
- free (esdo->rela.hashes);
- }
+ elf_final_link_free (abfd, &flinfo);
- elf_tdata (abfd)->linker = TRUE;
+ elf_linker (abfd) = TRUE;
if (attr_section)
{
return TRUE;
error_return:
- if (flinfo.symstrtab != NULL)
- _bfd_stringtab_free (flinfo.symstrtab);
- if (flinfo.contents != NULL)
- free (flinfo.contents);
- if (flinfo.external_relocs != NULL)
- free (flinfo.external_relocs);
- if (flinfo.internal_relocs != NULL)
- free (flinfo.internal_relocs);
- if (flinfo.external_syms != NULL)
- free (flinfo.external_syms);
- if (flinfo.locsym_shndx != NULL)
- free (flinfo.locsym_shndx);
- if (flinfo.internal_syms != NULL)
- free (flinfo.internal_syms);
- if (flinfo.indices != NULL)
- free (flinfo.indices);
- if (flinfo.sections != NULL)
- free (flinfo.sections);
- if (flinfo.symbuf != NULL)
- free (flinfo.symbuf);
- if (flinfo.symshndxbuf != NULL)
- free (flinfo.symshndxbuf);
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- struct bfd_elf_section_data *esdo = elf_section_data (o);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
- free (esdo->rel.hashes);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
- free (esdo->rela.hashes);
- }
-
+ elf_final_link_free (abfd, &flinfo);
return FALSE;
}
\f
reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags);
if (reloc_sec != NULL)
{
+ /* _bfd_elf_get_sec_type_attr chooses a section type by
+ name. Override as it may be wrong, eg. for a user
+ section named "auto" we'll get ".relauto" which is
+ seen to be a .rela section. */
+ elf_section_type (reloc_sec) = is_rela ? SHT_RELA : SHT_REL;
if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
reloc_sec = NULL;
}