/* ELF linking support for BFD.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009
+ 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
_bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
{
flagword flags;
- register asection *s;
+ asection *s;
const struct elf_backend_data *bed;
if (! is_elf_hash_table (info->hash))
if (provide && hidden)
{
- const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-
+ bed = get_elf_backend_data (output_bfd);
h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
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;
was referenced before. */
if (h->ref_regular)
{
- const struct elf_backend_data *bed
- = get_elf_backend_data (abfd);
struct elf_link_hash_entry *vh = *sym_hash;
+
vh->root.type = h->root.type;
h->root.type = bfd_link_hash_indirect;
(*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
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;
/* Handle the case where we had a versioned symbol in a dynamic
library and now find a definition in a normal object. In this
case, we make the versioned symbol point to the normal one. */
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
flip->root.type = h->root.type;
flip->root.u.undef.abfd = h->root.u.undef.abfd;
h->root.type = bfd_link_hash_indirect;
{
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;
}
bfd_boolean common;
unsigned int old_alignment;
bfd *old_bfd;
+ bfd * undef_bfd = NULL;
override = FALSE;
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 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.u.undef.abfd)
+ undef_bfd = h->root.u.undef.abfd;
+ }
+
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
&value, &old_alignment,
sym_hash, &skip, &override,
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
{
/* We don't want to make debug symbol dynamic. */
- (*bed->elf_backend_hide_symbol) (info, h, TRUE);
dynsym = FALSE;
}
/* 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: invalid DSO for symbol `%s' definition"),
+ (_("%B: undefined reference to symbol '%s'"),
+ undef_bfd, name);
+ (*_bfd_error_handler)
+ (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
abfd, name);
- bfd_set_error (bfd_error_bad_value);
+ bfd_set_error (bfd_error_invalid_operation);
goto error_free_vers;
}
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;
strip = FALSE;
/* If we're stripping it, and it's not a dynamic symbol, there's
- nothing else to do unless it is a forced local symbol. */
+ nothing else to do unless it is a forced local symbol or a
+ STT_GNU_IFUNC symbol. */
if (strip
&& h->dynindx == -1
+ && h->type != STT_GNU_IFUNC
&& !h->forced_local)
return TRUE;
bfd_boolean emit_relocs;
bfd *dynobj;
struct elf_final_link_info finfo;
- register asection *o;
- register struct bfd_link_order *p;
- register bfd *sub;
+ asection *o;
+ struct bfd_link_order *p;
+ bfd *sub;
bfd_size_type max_contents_size;
bfd_size_type max_external_reloc_size;
bfd_size_type max_internal_reloc_count;
if (size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
{
- struct bfd_link_order *o = sec->map_tail.link_order;
- if (o != NULL)
- size = o->offset + o->size;
+ struct bfd_link_order *ord = sec->map_tail.link_order;
+
+ if (ord != NULL)
+ size = ord->offset + ord->size;
}
end = sec->vma + size;
}
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;
}
o->gc_mark = first->gc_mark;
}
else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
- || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
+ || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0
+ || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE)
{
- /* Keep debug and special sections. */
+ /* Keep debug, special and SHT_NOTE sections. */
o->gc_mark = 1;
}
return reloc_sec;
}
+
+/* Copy the ELF symbol type associated with a linker hash entry. */
+void
+_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry * hdest,
+ struct bfd_link_hash_entry * hsrc)
+{
+ struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest;
+ struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc;
+
+ ehdest->type = ehsrc->type;
+}