/* ELF linking support for BFD.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
- Free Software Foundation, Inc.
+ Copyright 1995-2013 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
h->def_regular = 1;
h->non_elf = 0;
h->type = STT_OBJECT;
- h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+ h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
bed = get_elf_backend_data (abfd);
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
if (hidden)
{
bed = get_elf_backend_data (output_bfd);
- h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+ h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
bed = get_elf_backend_data (abfd);
- /* This code is for coping with dynamic objects, and is only useful
- if we are doing an ELF link. */
- if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
- return TRUE;
-
/* For merging, we only care about real symbols. But we need to make
sure that indirect symbol dynamic flags are updated. */
hi = h;
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
+ existing symbol. */
+
+ oldbfd = NULL;
+ oldsec = NULL;
+ switch (h->root.type)
+ {
+ default:
+ break;
+
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ oldbfd = h->root.u.undef.abfd;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ oldbfd = h->root.u.def.section->owner;
+ oldsec = h->root.u.def.section;
+ break;
+
+ case bfd_link_hash_common:
+ oldbfd = h->root.u.c.p->section->owner;
+ oldsec = h->root.u.c.p->section;
+ if (pold_alignment)
+ *pold_alignment = h->root.u.c.p->alignment_power;
+ break;
+ }
+ if (poldbfd && *poldbfd == NULL)
+ *poldbfd = oldbfd;
+
+ /* 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 (pold_weak)
+ *pold_weak = oldweak;
+
+ /* This code is for coping with dynamic objects, and is only useful
+ if we are doing an ELF link. */
+ if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
+ return TRUE;
+
/* We have to check it for every instance since the first few may be
references and not all compilers emit symbol type for undefined
symbols. */
return TRUE;
}
- /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
- existing symbol. */
-
- switch (h->root.type)
- {
- default:
- oldbfd = NULL;
- oldsec = NULL;
- break;
-
- case bfd_link_hash_undefined:
- case bfd_link_hash_undefweak:
- oldbfd = h->root.u.undef.abfd;
- oldsec = NULL;
- break;
-
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- oldbfd = h->root.u.def.section->owner;
- oldsec = h->root.u.def.section;
- break;
-
- case bfd_link_hash_common:
- oldbfd = h->root.u.c.p->section->owner;
- oldsec = h->root.u.c.p->section;
- if (pold_alignment)
- *pold_alignment = h->root.u.c.p->alignment_power;
- break;
- }
- if (poldbfd && *poldbfd == NULL)
- *poldbfd = oldbfd;
-
- /* 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 (pold_weak)
- *pold_weak = oldweak;
-
/* 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
bfd_boolean override;
char *p;
size_t len, shortlen;
+ asection *tmp_sec;
/* If this symbol has a version, and it is the default version, we
create an indirect symbol from the default name to the fully
actually going to define an indirect symbol. */
type_change_ok = FALSE;
size_change_ok = FALSE;
- if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, &value,
+ tmp_sec = sec;
+ if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
&hi, poldbfd, NULL, NULL, &skip, &override,
&type_change_ok, &size_change_ok))
return FALSE;
/* Once again, merge with any existing symbol. */
type_change_ok = FALSE;
size_change_ok = FALSE;
- if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, &value,
+ tmp_sec = sec;
+ if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
&hi, NULL, NULL, NULL, &skip, &override,
&type_change_ok, &size_change_ok))
return FALSE;
return ibed->relocs_compatible == obed->relocs_compatible;
}
+/* Make a special call to the linker "notice" function to tell it that
+ we are about to handle an as-needed lib, or have finished
+ processing the lib. */
+
+bfd_boolean
+_bfd_elf_notice_as_needed (bfd *ibfd,
+ struct bfd_link_info *info,
+ enum notice_asneeded_action act)
+{
+ return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
+}
+
/* Add symbols from an ELF object file to the linker hash table. */
static bfd_boolean
unsigned int old_size = 0;
unsigned int old_count = 0;
void *old_tab = NULL;
- void *old_hash;
void *old_ent;
struct bfd_link_hash_entry *old_undefs = NULL;
struct bfd_link_hash_entry *old_undefs_tail = NULL;
long old_dynsymcount = 0;
bfd_size_type old_dynstr_size = 0;
size_t tabsize = 0;
- size_t hashsize = 0;
+ asection *s;
htab = elf_hash_table (info);
bed = get_elf_backend_data (abfd);
symbol. This differs from .gnu.warning sections, which generate
warnings when they are included in an output file. */
/* PR 12761: Also generate this warning when building shared libraries. */
- if (info->executable || info->shared)
+ for (s = abfd->sections; s != NULL; s = s->next)
{
- asection *s;
+ const char *name;
- for (s = abfd->sections; s != NULL; s = s->next)
+ name = bfd_get_section_name (abfd, s);
+ if (CONST_STRNEQ (name, ".gnu.warning."))
{
- const char *name;
+ char *msg;
+ bfd_size_type sz;
+
+ name += sizeof ".gnu.warning." - 1;
- name = bfd_get_section_name (abfd, s);
- if (CONST_STRNEQ (name, ".gnu.warning."))
+ /* If this is a shared object, then look up the symbol
+ in the hash table. If it is there, and it is already
+ been defined, then we will not be using the entry
+ from this shared object, so we don't need to warn.
+ FIXME: If we see the definition in a regular object
+ later on, we will warn, but we shouldn't. The only
+ fix is to keep track of what warnings we are supposed
+ to emit, and then handle them all at the end of the
+ link. */
+ if (dynamic)
{
- char *msg;
- bfd_size_type sz;
-
- name += sizeof ".gnu.warning." - 1;
-
- /* If this is a shared object, then look up the symbol
- in the hash table. If it is there, and it is already
- been defined, then we will not be using the entry
- from this shared object, so we don't need to warn.
- FIXME: If we see the definition in a regular object
- later on, we will warn, but we shouldn't. The only
- fix is to keep track of what warnings we are supposed
- to emit, and then handle them all at the end of the
- link. */
- if (dynamic)
- {
- struct elf_link_hash_entry *h;
+ struct elf_link_hash_entry *h;
- h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
+ h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
- /* FIXME: What about bfd_link_hash_common? */
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- /* We don't want to issue this warning. Clobber
- the section size so that the warning does not
- get copied into the output file. */
- s->size = 0;
- continue;
- }
- }
+ /* FIXME: What about bfd_link_hash_common? */
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ continue;
+ }
- sz = s->size;
- msg = (char *) bfd_alloc (abfd, sz + 1);
- if (msg == NULL)
- goto error_return;
+ sz = s->size;
+ msg = (char *) bfd_alloc (abfd, sz + 1);
+ if (msg == NULL)
+ goto error_return;
- if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
- goto error_return;
+ if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
+ goto error_return;
- msg[sz] = '\0';
+ msg[sz] = '\0';
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, name, BSF_WARNING, s, 0, msg,
- FALSE, bed->collect, NULL)))
- goto error_return;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, name, BSF_WARNING, s, 0, msg,
+ FALSE, bed->collect, NULL)))
+ goto error_return;
- if (! info->relocatable)
- {
- /* Clobber the section size so that the warning does
- not get copied into the output file. */
- s->size = 0;
+ if (!info->relocatable && info->executable)
+ {
+ /* Clobber the section size so that the warning does
+ not get copied into the output file. */
+ s->size = 0;
- /* Also set SEC_EXCLUDE, so that symbols defined in
- the warning section don't get copied to the output. */
- s->flags |= SEC_EXCLUDE;
- }
+ /* Also set SEC_EXCLUDE, so that symbols defined in
+ the warning section don't get copied to the output. */
+ s->flags |= SEC_EXCLUDE;
}
}
}
goto error_return;
else
{
- asection *s;
const char *soname = NULL;
char *audit = NULL;
struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
extsymoff = hdr->sh_info;
}
- sym_hash = NULL;
+ sym_hash = elf_sym_hashes (abfd);
if (extsymcount != 0)
{
isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
if (isymbuf == NULL)
goto error_return;
- /* We store a pointer to the hash table entry for each external
- symbol. */
- amt = extsymcount * sizeof (struct elf_link_hash_entry *);
- sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
if (sym_hash == NULL)
- goto error_free_sym;
- elf_sym_hashes (abfd) = sym_hash;
+ {
+ /* We store a pointer to the hash table entry for each
+ external symbol. */
+ amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+ sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt);
+ if (sym_hash == NULL)
+ goto error_free_sym;
+ elf_sym_hashes (abfd) = sym_hash;
+ }
}
if (dynamic)
}
tabsize = htab->root.table.size * sizeof (struct bfd_hash_entry *);
- hashsize = extsymcount * sizeof (struct elf_link_hash_entry *);
- old_tab = bfd_malloc (tabsize + entsize + hashsize);
+ old_tab = bfd_malloc (tabsize + entsize);
if (old_tab == NULL)
goto error_free_vers;
/* Make a special call to the linker "notice" function to
tell it that we are about to handle an as-needed lib. */
- if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
- notice_as_needed, 0, NULL))
+ if (!(*bed->notice_as_needed) (abfd, info, notice_as_needed))
goto error_free_vers;
- /* Clone the symbol table and sym hashes. Remember some
- pointers into the symbol table, and dynamic symbol count. */
- old_hash = (char *) old_tab + tabsize;
- old_ent = (char *) old_hash + hashsize;
+ /* Clone the symbol table. Remember some pointers into the
+ symbol table, and dynamic symbol count. */
+ old_ent = (char *) old_tab + tabsize;
memcpy (old_tab, htab->root.table.table, tabsize);
- memcpy (old_hash, sym_hash, hashsize);
old_undefs = htab->root.undefs;
old_undefs_tail = htab->root.undefs_tail;
old_table = htab->root.table.table;
flags = BSF_NO_FLAGS;
sec = NULL;
value = isym->st_value;
- *sym_hash = NULL;
common = bed->common_definition (isym);
bind = ELF_ST_BIND (isym->st_info);
--no-add-needed is used and the reference was not
a weak one. */
if (old_bfd != NULL
- && h->ref_regular_nonweak
&& (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
{
(*_bfd_error_handler)
(_("%B: undefined reference to symbol '%s'"),
old_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_invalid_operation);
+ bfd_set_error (bfd_error_missing_dso);
goto error_free_vers;
}
unsigned int i;
/* Restore the symbol table. */
- if (bed->as_needed_cleanup)
- (*bed->as_needed_cleanup) (abfd, info);
- old_hash = (char *) old_tab + tabsize;
- old_ent = (char *) old_hash + hashsize;
- sym_hash = elf_sym_hashes (abfd);
+ old_ent = (char *) old_tab + tabsize;
+ memset (elf_sym_hashes (abfd), 0,
+ extsymcount * sizeof (struct elf_link_hash_entry *));
htab->root.table.table = old_table;
htab->root.table.size = old_size;
htab->root.table.count = old_count;
memcpy (htab->root.table.table, old_tab, tabsize);
- memcpy (sym_hash, old_hash, hashsize);
htab->root.undefs = old_undefs;
htab->root.undefs_tail = old_undefs_tail;
_bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
/* Make a special call to the linker "notice" function to
tell it that symbols added for crefs may need to be removed. */
- if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
- notice_not_needed, 0, NULL))
+ if (!(*bed->notice_as_needed) (abfd, info, notice_not_needed))
goto error_free_vers;
free (old_tab);
if (old_tab != NULL)
{
- if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
- notice_needed, 0, NULL))
+ if (!(*bed->notice_as_needed) (abfd, info, notice_needed))
goto error_free_vers;
free (old_tab);
old_tab = NULL;
struct elf_link_hash_entry *hlook;
asection *slook;
bfd_vma vlook;
- size_t i, j, idx;
+ size_t i, j, idx = 0;
hlook = weaks;
weaks = hlook->u.weakdef;
{
const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
- int copya, copyb;
- if (a->u.offset < b->u.offset)
+ if (a->type < b->type)
return -1;
- if (a->u.offset > b->u.offset)
+ if (a->type > b->type)
return 1;
- copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
- copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
- if (copya < copyb)
+ if (a->u.offset < b->u.offset)
return -1;
- if (copya > copyb)
+ if (a->u.offset > b->u.offset)
return 1;
if (a->rela->r_offset < b->rela->r_offset)
return -1;
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
(*swap_in) (abfd, erel, s->rela);
- s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
+ s->type = (*bed->elf_backend_reloc_type_class) (info, o, s->rela);
s->u.sym_mask = r_sym_mask;
p += sort_elt;
erel += ext_size;
{
asection *isec;
bfd_boolean some_kept;
+ bfd_boolean debug_frag_seen;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
- /* Ensure all linker created sections are kept, and see whether
- any other section is already marked. */
- some_kept = FALSE;
+ /* Ensure all linker created sections are kept,
+ see if any other section is already marked,
+ and note if we have any fragmented debug sections. */
+ debug_frag_seen = some_kept = FALSE;
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
{
if ((isec->flags & SEC_LINKER_CREATED) != 0)
isec->gc_mark = 1;
else if (isec->gc_mark)
some_kept = TRUE;
+
+ if (debug_frag_seen == FALSE
+ && (isec->flags & SEC_DEBUGGING)
+ && CONST_STRNEQ (isec->name, ".debug_line."))
+ debug_frag_seen = TRUE;
}
/* If no section in this file will be kept, then we can
- toss out debug sections. */
+ toss out the debug and special sections. */
if (!some_kept)
continue;
&& ((isec->flags & SEC_DEBUGGING) != 0
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
isec->gc_mark = 1;
+
+ if (! debug_frag_seen)
+ continue;
+
+ /* Look for CODE sections which are going to be discarded,
+ and find and discard any fragmented debug sections which
+ are associated with that code section. */
+ for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+ if ((isec->flags & SEC_CODE) != 0
+ && isec->gc_mark == 0)
+ {
+ unsigned int ilen;
+ asection *dsec;
+
+ ilen = strlen (isec->name);
+
+ /* Association is determined by the name of the debug section
+ containing the name of the code section as a suffix. For
+ example .debug_line.text.foo is a debug section associated
+ with .text.foo. */
+ for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+ {
+ unsigned int dlen;
+
+ if (dsec->gc_mark == 0
+ || (dsec->flags & SEC_DEBUGGING) == 0)
+ continue;
+
+ dlen = strlen (dsec->name);
+
+ if (dlen > ilen
+ && strncmp (dsec->name + (dlen - ilen),
+ isec->name, ilen) == 0)
+ {
+ dsec->gc_mark = 0;
+ break;
+ }
+ }
+ }
}
return TRUE;
}