break;
}
+ /* Differentiate strong and weak symbols. */
+ newweak = bind == STB_WEAK;
+ oldweak = (h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_undefweak);
+
/* In cases involving weak versioned symbols, we may wind up trying
to merge a symbol with itself. Catch that here, to avoid the
confusion that results if we try to override a symbol with
_GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a
dynamic object, which we do want to handle here. */
if (abfd == oldbfd
+ && (newweak || oldweak)
&& ((abfd->flags & DYNAMIC) == 0
|| !h->def_regular))
return TRUE;
return TRUE;
}
- /* Differentiate strong and weak symbols. */
- newweak = bind == STB_WEAK;
- oldweak = (h->root.type == bfd_link_hash_defweak
- || h->root.type == bfd_link_hash_undefweak);
-
if (bind == STB_GNU_UNIQUE)
h->unique_global = 1;
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
unsigned int vernum = 0;
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. */
+ if (! bfd_is_und_section (sec))
+ {
+ 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.u.undef.abfd)
+ undef_bfd = h->root.u.undef.abfd;
+ }
+
if (ever == NULL)
{
if (info->default_imported_symver)
name = newname;
}
- /* If this is a definition of a previously undefined symbol
- make a note of the bfd that contained the reference in
- case we need to refer to it later on in error messages. */
- if (! bfd_is_und_section (sec))
+ /* If necessary, make a second attempt to locate the bfd
+ containing an unresolved, non-weak 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);
if (h != NULL
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
+ && h->root.type == bfd_link_hash_undefined
&& h->root.u.undef.abfd)
undef_bfd = h->root.u.undef.abfd;
}
/* A symbol from a library loaded via DT_NEEDED of some
other library is referenced by a regular object.
Add a DT_NEEDED entry for it. Issue an error if
- --no-add-needed is used. */
- if ((elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
+ --no-add-needed is used and the reference was not
+ a weak one. */
+ if (undef_bfd != NULL
+ && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
{
(*_bfd_error_handler)
(_("%B: undefined reference to symbol '%s'"),
- undef_bfd == NULL ? info->output_bfd : undef_bfd, name);
+ undef_bfd, name);
(*_bfd_error_handler)
(_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
abfd, name);
return best_size;
}
+/* Size any SHT_GROUP section for ld -r. */
+
+bfd_boolean
+_bfd_elf_size_group_sections (struct bfd_link_info *info)
+{
+ bfd *ibfd;
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+ && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
+ return FALSE;
+ return TRUE;
+}
+
/* Set up the sizes and contents of the ELF dynamic sections. This is
called by the ELF linker emulation before_allocation routine. We
must set the sizes of the sections before the linker sets the
elf_hash_table (info)->init_plt_refcount
= elf_hash_table (info)->init_plt_offset;
+ if (info->relocatable
+ && !_bfd_elf_size_group_sections (info))
+ return FALSE;
+
/* The backend may have to create some sections regardless of whether
we're dynamic or not. */
if (bed->elf_backend_always_size_sections
{
struct bfd_elf_version_deps *n;
+ /* Don't emit base version twice. */
+ if (t->vernum == 0)
+ continue;
+
size += sizeof (Elf_External_Verdef);
size += sizeof (Elf_External_Verdaux);
++cdefs;
unsigned int cdeps;
struct bfd_elf_version_deps *n;
+ /* Don't emit the base version twice. */
+ if (t->vernum == 0)
+ continue;
+
cdeps = 0;
for (n = t->deps; n != NULL; n = n->next)
++cdeps;
def.vd_hash = bfd_elf_hash (t->name);
def.vd_aux = sizeof (Elf_External_Verdef);
def.vd_next = 0;
- if (t->next != NULL)
+
+ /* If a basever node is next, it *must* be the last node in
+ the chain, otherwise Verdef construction breaks. */
+ if (t->next != NULL && t->next->vernum == 0)
+ BFD_ASSERT (t->next->next == NULL);
+
+ if (t->next != NULL && t->next->vernum != 0)
def.vd_next = (sizeof (Elf_External_Verdef)
+ (cdeps + 1) * sizeof (Elf_External_Verdaux));
unsigned int crefs;
bfd_byte *p;
- /* Build the version definition section. */
+ /* Build the version dependency section. */
size = 0;
crefs = 0;
for (t = elf_tdata (output_bfd)->verref;
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
- unsigned int entsize)
+ unsigned int entsize,
+ enum elf_target_id target_id)
{
bfd_boolean ret;
int can_refcount = get_elf_backend_data (abfd)->can_refcount;
table->dynsymcount = 1;
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
+
table->root.type = bfd_link_elf_hash_table;
+ table->hash_table_id = target_id;
return ret;
}
return NULL;
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ GENERIC_ELF_DATA))
{
free (ret);
return NULL;
_bfd_elf_swap_versym_in (input, ever, &iver);
- if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
+ if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+ && !(h->def_regular
+ && h->forced_local))
{
/* If we have a non-hidden versioned sym, then it should
- have provided a definition for the undefined sym. */
+ have provided a definition for the undefined sym unless
+ it is defined in a non-shared object and forced local.
+ */
abort ();
}
{
/* If we have an undefined symbol reference here then it must have
come from a shared library that is being linked in. (Undefined
- references in regular files have already been handled). */
+ references in regular files have already been handled unless
+ they are in unreferenced sections which are removed by garbage
+ collection). */
bfd_boolean ignore_undef = FALSE;
/* Some symbols may be special in that the fact that they're
/* If we are reporting errors for this situation then do so now. */
if (ignore_undef == FALSE
&& h->ref_dynamic
- && ! h->ref_regular
+ && (!h->ref_regular || finfo->info->gc_sections)
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h)
&& finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
{
if (! (finfo->info->callbacks->undefined_symbol
- (finfo->info, h->root.root.string, h->root.u.undef.abfd,
+ (finfo->info, h->root.root.string,
+ h->ref_regular ? NULL : h->root.u.undef.abfd,
NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)))
{
eoinfo->failed = TRUE;
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
+ const char *sec_name;
+
if (h != NULL)
{
switch (h->root.type)
case bfd_link_hash_common:
return h->root.u.c.p->section;
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ /* To work around a glibc bug, keep all XXX input sections
+ when there is an as yet undefined reference to __start_XXX
+ or __stop_XXX symbols. The linker will later define such
+ symbols for orphan input sections that have a name
+ representable as a C identifier. */
+ if (strncmp (h->root.root.string, "__start_", 8) == 0)
+ sec_name = h->root.root.string + 8;
+ else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+ sec_name = h->root.root.string + 7;
+ else
+ sec_name = NULL;
+
+ if (sec_name && *sec_name != '\0')
+ {
+ bfd *i;
+
+ for (i = info->input_bfds; i; i = i->link_next)
+ {
+ sec = bfd_get_section_by_name (i, sec_name);
+ if (sec)
+ sec->flags |= SEC_KEEP;
+ }
+ }
+ break;
+
default:
break;
}