/* ELF linking support for BFD.
- Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "sysdep.h"
#include "bfd.h"
-#include "bfd_stdint.h"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
if ((ibfd->flags
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0
&& bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+ && elf_object_id (ibfd) == elf_hash_table_id (hash_table)
&& !((s = ibfd->sections) != NULL
&& s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS))
{
|| (d != NULL
&& h->non_elf
&& (*d->match) (&d->head, NULL, h->root.root.string)))
- h->dynamic = 1;
+ {
+ h->dynamic = 1;
+ /* NB: If a symbol is made dynamic by --dynamic-list, it has
+ non-IR reference. */
+ h->root.non_ir_ref_dynamic = 1;
+ }
}
/* Record an assignment to a symbol made by a linker script. We need
&& !h->def_regular)
h->root.type = bfd_link_hash_undefined;
- /* If this symbol is not being provided by the linker script, and it is
- currently defined by a dynamic object, but not by a regular object,
- then clear out any version information because the symbol will not be
- associated with the dynamic object any more. */
- if (!provide
- && h->def_dynamic
- && !h->def_regular)
+ /* If this symbol is currently defined by a dynamic object, but not
+ by a regular object, then clear out any version information because
+ the symbol will not be associated with the dynamic object any
+ more. */
+ if (h->def_dynamic && !h->def_regular)
h->verinfo.verdef = NULL;
/* Make sure this symbol is not garbage collected. */
|| h->ref_dynamic
|| bfd_link_dll (info)
|| elf_hash_table (info)->is_relocatable_executable)
+ && !h->forced_local
&& h->dynindx == -1)
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
/* Return true if the dynamic symbol for a given section should be
omitted when creating a shared library. */
bfd_boolean
-_bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info,
- asection *p)
+_bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
+ asection *p)
{
struct elf_link_hash_table *htab;
asection *ip;
}
}
+bfd_boolean
+_bfd_elf_omit_section_dynsym_all
+ (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *p ATTRIBUTE_UNUSED)
+{
+ return TRUE;
+}
+
/* Assign dynsym indices. In a shared library we generate a section
symbol for each output section, which come first. Next come symbols
which have been forced to local binding. Then all of the back-end
for (p = output_bfd->sections; p ; p = p->next)
if ((p->flags & SEC_EXCLUDE) == 0
&& (p->flags & SEC_ALLOC) != 0
+ && elf_hash_table (info)->dynamic_relocs
&& !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
{
++dynsymcount;
if (tdef && ntdef)
_bfd_error_handler
/* xgettext:c-format */
- (_("%s: TLS definition in %B section %A "
- "mismatches non-TLS definition in %B section %A"),
+ (_("%s: TLS definition in %pB section %pA "
+ "mismatches non-TLS definition in %pB section %pA"),
h->root.root.string, tbfd, tsec, ntbfd, ntsec);
else if (!tdef && !ntdef)
_bfd_error_handler
/* xgettext:c-format */
- (_("%s: TLS reference in %B "
- "mismatches non-TLS reference in %B"),
+ (_("%s: TLS reference in %pB "
+ "mismatches non-TLS reference in %pB"),
h->root.root.string, tbfd, ntbfd);
else if (tdef)
_bfd_error_handler
/* xgettext:c-format */
- (_("%s: TLS definition in %B section %A "
- "mismatches non-TLS reference in %B"),
+ (_("%s: TLS definition in %pB section %pA "
+ "mismatches non-TLS reference in %pB"),
h->root.root.string, tbfd, tsec, ntbfd);
else
_bfd_error_handler
/* xgettext:c-format */
- (_("%s: TLS reference in %B "
- "mismatches non-TLS definition in %B section %A"),
+ (_("%s: TLS reference in %pB "
+ "mismatches non-TLS definition in %pB section %pA"),
h->root.root.string, tbfd, ntbfd, ntsec);
bfd_set_error (bfd_error_bad_value);
if (! bfd_link_relocatable (info))
{
bh = &hi->root;
+ if (bh->type == bfd_link_hash_defined
+ && bh->u.def.section->owner != NULL
+ && (bh->u.def.section->owner->flags & BFD_PLUGIN) != 0)
+ {
+ /* Mark the previous definition from IR object as
+ undefined so that the generic linker will override
+ it. */
+ bh->type = bfd_link_hash_undefined;
+ bh->u.undef.abfd = bh->u.def.section->owner;
+ }
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT,
bfd_ind_section_ptr,
&& hi->root.type != bfd_link_hash_defweak)
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unexpected redefinition of indirect versioned symbol `%s'"),
+ (_("%pB: unexpected redefinition of indirect versioned symbol `%s'"),
abfd, shortname);
}
else
return TRUE;
}
+/* Return TRUE and set *HIDE to TRUE if the versioned symbol is
+ hidden. Set *T_P to NULL if there is no match. */
+
+static bfd_boolean
+_bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ const char *version_p,
+ struct bfd_elf_version_tree **t_p,
+ bfd_boolean *hide)
+{
+ struct bfd_elf_version_tree *t;
+
+ /* Look for the version. If we find it, it is no longer weak. */
+ for (t = info->version_info; t != NULL; t = t->next)
+ {
+ if (strcmp (t->name, version_p) == 0)
+ {
+ size_t len;
+ char *alc;
+ struct bfd_elf_version_expr *d;
+
+ len = version_p - h->root.root.string;
+ alc = (char *) bfd_malloc (len);
+ if (alc == NULL)
+ return FALSE;
+ memcpy (alc, h->root.root.string, len - 1);
+ alc[len - 1] = '\0';
+ if (alc[len - 2] == ELF_VER_CHR)
+ alc[len - 2] = '\0';
+
+ h->verinfo.vertree = t;
+ t->used = TRUE;
+ d = NULL;
+
+ if (t->globals.list != NULL)
+ d = (*t->match) (&t->globals, NULL, alc);
+
+ /* See if there is anything to force this symbol to
+ local scope. */
+ if (d == NULL && t->locals.list != NULL)
+ {
+ d = (*t->match) (&t->locals, NULL, alc);
+ if (d != NULL
+ && h->dynindx != -1
+ && ! info->export_dynamic)
+ *hide = TRUE;
+ }
+
+ free (alc);
+ break;
+ }
+ }
+
+ *t_p = t;
+
+ return TRUE;
+}
+
+/* Return TRUE if the symbol H is hidden by version script. */
+
+bfd_boolean
+_bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ const char *p;
+ bfd_boolean hide = FALSE;
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (info->output_bfd);
+
+ /* Version script only hides symbols defined in regular objects. */
+ if (!h->def_regular && !ELF_COMMON_DEF_P (h))
+ return TRUE;
+
+ p = strchr (h->root.root.string, ELF_VER_CHR);
+ if (p != NULL && h->verinfo.vertree == NULL)
+ {
+ struct bfd_elf_version_tree *t;
+
+ ++p;
+ if (*p == ELF_VER_CHR)
+ ++p;
+
+ if (*p != '\0'
+ && _bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide)
+ && hide)
+ {
+ if (hide)
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+ return TRUE;
+ }
+ }
+
+ /* If we don't have a version for this symbol, see if we can find
+ something. */
+ if (h->verinfo.vertree == NULL && info->version_info != NULL)
+ {
+ h->verinfo.vertree
+ = bfd_find_version_for_sym (info->version_info,
+ h->root.root.string, &hide);
+ if (h->verinfo.vertree != NULL && hide)
+ {
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/* Figure out appropriate versions for all the symbols. We may not
have the version number script until we have read all of the input
files, so until that point we don't know which symbols should be
const struct elf_backend_data *bed;
struct elf_info_failed eif;
char *p;
+ bfd_boolean hide;
sinfo = (struct elf_info_failed *) data;
info = sinfo->info;
return FALSE;
}
+ bed = get_elf_backend_data (info->output_bfd);
+
/* We only need version numbers for symbols defined in regular
objects. */
if (!h->def_regular)
- return TRUE;
+ {
+ /* Hide symbols defined in discarded input sections. */
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && discarded_section (h->root.u.def.section))
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+ return TRUE;
+ }
- bed = get_elf_backend_data (info->output_bfd);
+ hide = FALSE;
p = strchr (h->root.root.string, ELF_VER_CHR);
if (p != NULL && h->verinfo.vertree == NULL)
{
if (*p == '\0')
return TRUE;
- /* Look for the version. If we find it, it is no longer weak. */
- for (t = sinfo->info->version_info; t != NULL; t = t->next)
+ if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide))
{
- if (strcmp (t->name, p) == 0)
- {
- size_t len;
- char *alc;
- struct bfd_elf_version_expr *d;
-
- len = p - h->root.root.string;
- alc = (char *) bfd_malloc (len);
- if (alc == NULL)
- {
- sinfo->failed = TRUE;
- return FALSE;
- }
- memcpy (alc, h->root.root.string, len - 1);
- alc[len - 1] = '\0';
- if (alc[len - 2] == ELF_VER_CHR)
- alc[len - 2] = '\0';
-
- h->verinfo.vertree = t;
- t->used = TRUE;
- d = NULL;
-
- if (t->globals.list != NULL)
- d = (*t->match) (&t->globals, NULL, alc);
-
- /* See if there is anything to force this symbol to
- local scope. */
- if (d == NULL && t->locals.list != NULL)
- {
- d = (*t->match) (&t->locals, NULL, alc);
- if (d != NULL
- && h->dynindx != -1
- && ! info->export_dynamic)
- (*bed->elf_backend_hide_symbol) (info, h, TRUE);
- }
-
- free (alc);
- break;
- }
+ sinfo->failed = TRUE;
+ return FALSE;
}
+ if (hide)
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+
/* If we are building an application, we need to create a
version node for this version. */
if (t == NULL && bfd_link_executable (info))
generating a shared archive. Return an error. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: version node not found for symbol %s"),
+ (_("%pB: version node not found for symbol %s"),
info->output_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
sinfo->failed = TRUE;
/* If we don't have a version for this symbol, see if we can find
something. */
- if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL)
+ if (!hide
+ && h->verinfo.vertree == NULL
+ && sinfo->info->version_info != NULL)
{
- bfd_boolean hide;
-
h->verinfo.vertree
= bfd_find_version_for_sym (sinfo->info->version_info,
h->root.root.string, &hide);
}
erela = (const bfd_byte *) external_relocs;
- erelaend = erela + shdr->sh_size;
+ /* Setting erelaend like this and comparing with <= handles case of
+ a fuzzed object with sh_size not a multiple of sh_entsize. */
+ erelaend = erela + shdr->sh_size - shdr->sh_entsize;
irela = internal_relocs;
- while (erela < erelaend)
+ while (erela <= erelaend)
{
bfd_vma r_symndx;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: bad reloc symbol index (%#Lx >= %#lx)"
- " for offset %#Lx in section `%A'"),
- abfd, r_symndx, (unsigned long) nsyms,
- irela->r_offset, sec);
+ (_("%pB: bad reloc symbol index (%#" PRIx64 " >= %#lx)"
+ " for offset %#" PRIx64 " in section `%pA'"),
+ abfd, (uint64_t) r_symndx, (unsigned long) nsyms,
+ (uint64_t) irela->r_offset, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: non-zero symbol index (%#Lx)"
- " for offset %#Lx in section `%A'"
+ (_("%pB: non-zero symbol index (%#" PRIx64 ")"
+ " for offset %#" PRIx64 " in section `%pA'"
" when the object file has no symbol table"),
- abfd, r_symndx,
- irela->r_offset, sec);
+ abfd, (uint64_t) r_symndx,
+ (uint64_t) irela->r_offset, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: relocation size mismatch in %B section %A"),
+ (_("%pB: relocation size mismatch in %pB section %pA"),
output_bfd, input_section->owner, input_section);
bfd_set_error (bfd_error_wrong_format);
return FALSE;
&& (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
h->def_regular = 1;
+ /* Symbols defined in discarded sections shouldn't be dynamic. */
+ if (h->root.type == bfd_link_hash_undefined && h->indx == -3)
+ (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
/* If a weak undefined symbol has non-default visibility, we also
hide it from the dynamic linker. */
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
- && h->root.type == bfd_link_hash_undefweak)
+ else if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak)
(*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
/* A hidden versioned symbol in executable should be forced local if
|| (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"),
+ (_("%P: copy reloc against protected `%pT' is dangerous\n"),
h->root.root.string);
return TRUE;
if (! is_elf_hash_table (hash_table))
return FALSE;
+ if (tag == DT_RELA || tag == DT_REL)
+ hash_table->dynamic_relocs = TRUE;
+
bed = get_elf_backend_data (hash_table->dynobj);
s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
BFD_ASSERT (s != NULL);
struct elf_link_hash_entry **sym_hash;
bfd_boolean dynamic;
Elf_External_Versym *extversym = NULL;
+ Elf_External_Versym *extversym_end = NULL;
Elf_External_Versym *ever;
struct elf_link_hash_entry *weaks;
struct elf_link_hash_entry **nondeflt_vers = NULL;
&& ehdr->e_machine == bed->elf_machine_alt1)
|| (bed->elf_machine_alt2 != 0
&& ehdr->e_machine == bed->elf_machine_alt2)))
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
+ (_("alternate ELF machine code found (%d) in %pB, expecting %d"),
ehdr->e_machine, abfd, bed->elf_machine_code);
/* As a GNU extension, any input sections which are named
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
for (extdyn = dynbuf;
- extdyn < dynbuf + s->size;
+ extdyn <= dynbuf + s->size - bed->s->sizeof_dyn;
extdyn += bed->s->sizeof_dyn)
{
Elf_Internal_Dyn dyn;
all sections contained fully therein. This makes relro
shared library sections appear as they will at run-time. */
phdr = elf_tdata (abfd)->phdr + elf_elfheader (abfd)->e_phnum;
- while (--phdr >= elf_tdata (abfd)->phdr)
+ while (phdr-- > elf_tdata (abfd)->phdr)
if (phdr->p_type == PT_GNU_RELRO)
{
for (s = abfd->sections; s != NULL; s = s->next)
Elf_Internal_Shdr *versymhdr;
versymhdr = &elf_tdata (abfd)->dynversym_hdr;
- extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+ amt = versymhdr->sh_size;
+ extversym = (Elf_External_Versym *) bfd_malloc (amt);
if (extversym == NULL)
goto error_free_sym;
- amt = versymhdr->sh_size;
if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
|| bfd_bread (extversym, amt, abfd) != amt)
goto error_free_vers;
+ extversym_end = extversym + (amt / sizeof (* extversym));
}
}
}
weaks = NULL;
- ever = extversym != NULL ? extversym + extsymoff : NULL;
+ if (extversym == NULL)
+ ever = NULL;
+ else if (extversym + extsymoff < extversym_end)
+ ever = extversym + extsymoff;
+ else
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: invalid version offset %lx (max %lx)"),
+ abfd, (long) extsymoff,
+ (long) (extversym_end - extversym) / sizeof (* extversym));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_free_vers;
+ }
+
for (isym = isymbuf, isymend = isymbuf + extsymcount;
isym < isymend;
isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
global symbols follow all local symbols, and that sh_info
point to the first global symbol. Unfortunately, Irix 5
screws this up. */
- continue;
+ if (elf_bad_symtab (abfd))
+ continue;
+
+ /* If we aren't prepared to handle locals within the globals
+ then we'll likely segfault on a NULL section. */
+ bfd_set_error (bfd_error_bad_value);
+ goto error_free_vers;
case STB_GLOBAL:
if (isym->st_shndx != SHN_UNDEF && !common)
else
iver.vs_vers = 0;
}
+ else if (ever >= extversym_end)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: not enough version information"),
+ abfd);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_free_vers;
+ }
else
_bfd_elf_swap_versym_in (abfd, ever, &iver);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: %s: invalid version %u (max %d)"),
+ (_("%pB: %s: invalid version %u (max %d)"),
abfd, name, vernum,
elf_tdata (abfd)->cverdefs);
bfd_set_error (bfd_error_bad_value);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: %s: invalid needed version %d"),
+ (_("%pB: %s: invalid needed version %d"),
abfd, name, vernum);
bfd_set_error (bfd_error_bad_value);
goto error_free_vers;
(struct bfd_link_hash_entry **) sym_hash)))
goto error_free_vers;
- if ((flags & BSF_GNU_UNIQUE)
- && (abfd->flags & DYNAMIC) == 0
- && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
- elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique;
+ if ((abfd->flags & DYNAMIC) == 0
+ && (bfd_get_flavour (info->output_bfd)
+ == bfd_target_elf_flavour))
+ {
+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+ elf_tdata (info->output_bfd)->has_gnu_symbols
+ |= elf_gnu_symbol_ifunc;
+ if ((flags & BSF_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols
+ |= elf_gnu_symbol_unique;
+ }
h = *sym_hash;
/* We need to make sure that indirect symbol dynamic flags are
if (normal_bfd == NULL)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: alignment %u of common symbol `%s' in %B is"
- " greater than the alignment (%u) of its section %A"),
+ (_("warning: alignment %u of common symbol `%s' in %pB is"
+ " greater than the alignment (%u) of its section %pA"),
1 << common_align, name, common_bfd,
1 << normal_align, h->root.u.def.section);
else
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: alignment %u of symbol `%s' in %B"
- " is smaller than %u in %B"),
+ (_("warning: alignment %u of symbol `%s' in %pB"
+ " is smaller than %u in %pB"),
1 << normal_align, name, normal_bfd,
1 << common_align, common_bfd);
}
&& ! size_change_ok)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: size of symbol `%s' changed"
- " from %Lu in %B to %Lu in %B"),
- name, h->size, old_bfd, isym->st_size, abfd);
+ (_("warning: size of symbol `%s' changed"
+ " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
+ name, (uint64_t) h->size, old_bfd,
+ (uint64_t) isym->st_size, abfd);
h->size = isym->st_size;
}
if (h->type != STT_NOTYPE && ! type_change_ok)
/* xgettext:c-format */
_bfd_error_handler
- (_("Warning: type of symbol `%s' changed"
- " from %d to %d in %B"),
+ (_("warning: type of symbol `%s' changed"
+ " from %d to %d in %pB"),
name, h->type, type, abfd);
h->type = type;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: undefined reference to symbol '%s'"),
+ (_("%pB: undefined reference to symbol '%s'"),
old_bfd, name);
bfd_set_error (bfd_error_missing_dso);
goto error_free_vers;
len = strlen (name);
copy = (char *) bfd_alloc (abfd, len);
if (copy == NULL)
- return (struct elf_link_hash_entry *) 0 - 1;
+ return (struct elf_link_hash_entry *) -1;
first = p - name + 1;
memcpy (copy, name, first);
}
h = archive_symbol_lookup (abfd, info, symdef->name);
- if (h == (struct elf_link_hash_entry *) 0 - 1)
+ if (h == (struct elf_link_hash_entry *) -1)
goto error_return;
if (h == NULL)
h->type = STT_OBJECT;
if (info->stacksize)
/* xgettext:c-format */
- _bfd_error_handler (_("%B: stack size specified and %s set"),
+ _bfd_error_handler (_("%pB: stack size specified and %s set"),
output_bfd, legacy_symbol);
else if (h->root.u.def.section != bfd_abs_section_ptr)
/* xgettext:c-format */
- _bfd_error_handler (_("%B: %s not absolute"),
+ _bfd_error_handler (_("%pB: %s not absolute"),
output_bfd, legacy_symbol);
else
info->stacksize = h->root.u.def.value;
== SHT_PREINIT_ARRAY)
{
_bfd_error_handler
- (_("%B: .preinit_array section is not allowed in DSO"),
+ (_("%pB: .preinit_array section is not allowed in DSO"),
sub);
break;
}
for (s = output_bfd->sections; s != NULL; s = s->next)
if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
- && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
elf_hash_table (info)->text_index_section = s;
break;
asection *s;
/* Data first, since setting text_index_section changes
- _bfd_elf_link_omit_section_dynsym. */
+ _bfd_elf_omit_section_dynsym_default. */
for (s = output_bfd->sections; s != NULL; s = s->next)
if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
- && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
elf_hash_table (info)->data_index_section = s;
break;
for (s = output_bfd->sections; s != NULL; s = s->next)
if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
== (SEC_ALLOC | SEC_READONLY))
- && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
elf_hash_table (info)->text_index_section = s;
break;
}
}
+/* Hide a symbol. */
+
+void
+_bfd_elf_link_hide_symbol (bfd *output_bfd,
+ struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h)
+{
+ if (is_elf_hash_table (info->hash))
+ {
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (output_bfd);
+ struct elf_link_hash_entry *eh
+ = (struct elf_link_hash_entry *) h;
+ bed->elf_backend_hide_symbol (info, eh, TRUE);
+ eh->def_dynamic = 0;
+ eh->ref_dynamic = 0;
+ eh->dynamic_def = 0;
+ }
+}
+
/* Initialize an ELF linker hash table. *TABLE has been zeroed by our
caller. */
&& ! info->gc_keep_exported)
{
/* PR 21524: Let the user know if a symbol was removed by garbage collection. */
- _bfd_error_handler (_("%B:%A: error: relocation references symbol %s which was removed by garbage collection."),
+ _bfd_error_handler (_("%pB:%pA: error: relocation references symbol %s which was removed by garbage collection"),
abfd, sec,
(*rel_hash)->root.root.string);
- _bfd_error_handler (_("%B:%A: error: try relinking with --gc-keep-exported enabled."),
+ _bfd_error_handler (_("%pB:%pA: error: try relinking with --gc-keep-exported enabled"),
abfd, sec);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
/* Section size is only divisible by rela. */
if (use_rela_initialised && !use_rela)
{
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are in more than one size"),
abfd);
bfd_set_error (bfd_error_invalid_operation);
/* Section size is only divisible by rel. */
if (use_rela_initialised && use_rela)
{
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are in more than one size"),
abfd);
bfd_set_error (bfd_error_invalid_operation);
{
/* The section size is not divisible by either -
something is wrong. */
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are of an unknown size"), abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
/* Section size is only divisible by rela. */
if (use_rela_initialised && !use_rela)
{
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are in more than one size"),
abfd);
bfd_set_error (bfd_error_invalid_operation);
/* Section size is only divisible by rel. */
if (use_rela_initialised && use_rela)
{
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are in more than one size"),
abfd);
bfd_set_error (bfd_error_invalid_operation);
{
/* The section size is not divisible by either -
something is wrong. */
- _bfd_error_handler (_("%B: Unable to sort relocs - "
+ _bfd_error_handler (_("%pB: unable to sort relocs - "
"they are of an unknown size"), abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
if (sort == NULL)
{
(*info->callbacks->warning)
- (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
+ (info, _("not enough memory to sort relocations"), 0, abfd, 0, 0);
return 0;
}
beyond 64k. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: Too many sections: %d (>= %d)"),
+ (_("%pB: too many sections: %d (>= %d)"),
abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
/* If we are reporting errors for this situation then do so now. */
if (!ignore_undef
- && h->ref_dynamic
+ && h->ref_dynamic_nonweak
&& (!h->ref_regular || flinfo->info->gc_sections)
&& !elf_link_check_versioned_symbol (flinfo->info, bed, h)
&& flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
/* xgettext:c-format */
- msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
+ msg = _("%pB: internal symbol `%s' in %pB is referenced by DSO");
else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
/* xgettext:c-format */
- msg = _("%B: hidden symbol `%s' in %B is referenced by DSO");
+ msg = _("%pB: hidden symbol `%s' in %pB is referenced by DSO");
else
/* xgettext:c-format */
- msg = _("%B: local symbol `%s' in %B is referenced by DSO");
+ msg = _("%pB: local symbol `%s' in %pB is referenced by DSO");
def_bfd = flinfo->output_bfd;
if (hi->root.u.def.section != bfd_abs_section_ptr)
def_bfd = hi->root.u.def.section->owner;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: could not find output section %A for input section %A"),
+ (_("%pB: could not find output section %pA for input section %pA"),
flinfo->output_bfd, input_sec->output_section, input_sec);
bfd_set_error (bfd_error_nonrepresentable_section);
eoinfo->failed = TRUE;
if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED)
/* xgettext:c-format */
- msg = _("%B: protected symbol `%s' isn't defined");
+ msg = _("%pB: protected symbol `%s' isn't defined");
else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL)
/* xgettext:c-format */
- msg = _("%B: internal symbol `%s' isn't defined");
+ msg = _("%pB: internal symbol `%s' isn't defined");
else
/* xgettext:c-format */
- msg = _("%B: hidden symbol `%s' isn't defined");
+ msg = _("%pB: hidden symbol `%s' isn't defined");
_bfd_error_handler (msg, flinfo->output_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
/* If this symbol should be put in the .dynsym section, then put it
there now. We already know the symbol index. We also fill in
the entry in the .hash section. */
- if (elf_hash_table (flinfo->info)->dynsym != NULL
- && h->dynindx != -1
- && elf_hash_table (flinfo->info)->dynamic_sections_created)
+ if (h->dynindx != -1
+ && elf_hash_table (flinfo->info)->dynamic_sections_created
+ && elf_hash_table (flinfo->info)->dynsym != NULL
+ && !discarded_section (elf_hash_table (flinfo->info)->dynsym))
{
bfd_byte *esym;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: No symbol version section for versioned symbol `%s'"),
+ (_("%pB: no symbol version section for versioned symbol `%s'"),
flinfo->output_bfd, h->root.root.string);
eoinfo->failed = TRUE;
return FALSE;
{
/* Don't attempt to output symbols with st_shnx in the
reserved range other than SHN_ABS and SHN_COMMON. */
- *ppsection = NULL;
- continue;
+ isec = bfd_und_section_ptr;
}
else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE
&& ELF_ST_TYPE (isym->st_info) != STT_SECTION)
if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
{
/* STT_TLS symbols are relative to PT_TLS segment base. */
- BFD_ASSERT (elf_hash_table (flinfo->info)->tls_sec != NULL);
- osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma;
+ if (elf_hash_table (flinfo->info)->tls_sec != NULL)
+ osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma;
+ else
+ osym.st_info = ELF_ST_INFO (ELF_ST_BIND (osym.st_info),
+ STT_NOTYPE);
}
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %B: size of section %A is not "
+ (_("error: %pB: size of section %pA is not "
"multiple of address size"),
input_bfd, o);
bfd_set_error (bfd_error_bad_value);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %B contains a reloc (%#Lx) for section %A "
+ (_("error: %pB contains a reloc (%#" PRIx64 ") for section %pA "
"that references a non-existent global symbol"),
- input_bfd, rel->r_info, o);
+ input_bfd, (uint64_t) rel->r_info, o);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
if (action_discarded & COMPLAIN)
(*flinfo->info->callbacks->einfo)
/* xgettext:c-format */
- (_("%X`%s' referenced in section `%A' of %B: "
- "defined in discarded section `%A' of %B\n"),
+ (_("%X`%s' referenced in section `%pA' of %pB: "
+ "defined in discarded section `%pA' of %pB\n"),
sym_name, o, input_bfd, sec, sec->owner);
/* Try to do the best we can to support buggy old
sym.st_value += osec->vma;
if (ELF_ST_TYPE (sym.st_info) == STT_TLS)
{
+ struct elf_link_hash_table *htab
+ = elf_hash_table (flinfo->info);
+
/* STT_TLS symbols are relative to PT_TLS
segment base. */
- BFD_ASSERT (elf_hash_table (flinfo->info)
- ->tls_sec != NULL);
- sym.st_value -= (elf_hash_table (flinfo->info)
- ->tls_sec->vma);
+ if (htab->tls_sec != NULL)
+ sym.st_value -= htab->tls_sec->vma;
+ else
+ sym.st_info
+ = ELF_ST_INFO (ELF_ST_BIND (sym.st_info),
+ STT_NOTYPE);
}
}
if (bed->link_order_error_handler)
bed->link_order_error_handler
/* xgettext:c-format */
- (_("%B: warning: sh_link not set for section `%A'"), s->owner, s);
+ (_("%pB: warning: sh_link not set for section `%pA'"), s->owner, s);
return 0;
}
else
if (other_sec && linkorder_sec)
_bfd_error_handler
/* xgettext:c-format */
- (_("%A has both ordered [`%A' in %B] "
- "and unordered [`%A' in %B] sections"),
+ (_("%pA has both ordered [`%pA' in %pB] "
+ "and unordered [`%pA' in %pB] sections"),
o, linkorder_sec, linkorder_sec->owner,
other_sec, other_sec->owner);
else
_bfd_error_handler
- (_("%A has both ordered and unordered sections"), o);
+ (_("%pA has both ordered and unordered sections"), o);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
if (symcount == 0)
{
bfd_set_error (bfd_error_no_symbols);
- _bfd_error_handler (_("%B: no symbol found for import library"),
+ _bfd_error_handler (_("%pB: no symbol found for import library"),
implib_bfd);
goto free_sym_buf;
}
free (flinfo->indices);
if (flinfo->sections != NULL)
free (flinfo->sections);
- if (flinfo->symshndxbuf != NULL)
+ if (flinfo->symshndxbuf != NULL
+ && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
free (flinfo->symshndxbuf);
for (o = obfd->sections; o != NULL; o = o->next)
{
std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
for (o = abfd->sections; o != NULL; o = o->next)
{
+ bfd_boolean remove_section = FALSE;
+
if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
|| strcmp (o->name, ".gnu.attributes") == 0)
{
}
attr_size = bfd_elf_obj_attr_size (abfd);
+ bfd_set_section_size (abfd, o, attr_size);
+ /* Skip this section later on. */
+ o->map_head.link_order = NULL;
if (attr_size)
- {
- bfd_set_section_size (abfd, o, attr_size);
- attr_section = o;
- /* Skip this section later on. */
- o->map_head.link_order = NULL;
- }
+ attr_section = o;
else
- o->flags |= SEC_EXCLUDE;
+ remove_section = TRUE;
+ }
+ else if ((o->flags & SEC_GROUP) != 0 && o->size == 0)
+ {
+ /* Remove empty group section from linker output. */
+ remove_section = TRUE;
+ }
+ if (remove_section)
+ {
+ o->flags |= SEC_EXCLUDE;
+ bfd_section_list_remove (abfd, o);
+ abfd->section_count--;
}
}
bfd_set_error (bfd_error_wrong_format);
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: file class %s incompatible with %s"),
+ (_("%pB: file class %s incompatible with %s"),
sub, iclass, oclass);
}
if (info->out_implib_bfd && !elf_output_implib (abfd, info))
{
- _bfd_error_handler (_("%B: failed to generate import library"),
+ _bfd_error_handler (_("%pB: failed to generate import library"),
info->out_implib_bfd);
return FALSE;
}
{
if (info->error_textrel)
info->callbacks->einfo
- (_("%P%X: read-only segment has dynamic relocations.\n"));
+ (_("%P%X: read-only segment has dynamic relocations\n"));
else
info->callbacks->einfo
- (_("%P: warning: creating a DT_TEXTREL in a shared object.\n"));
+ (_("%P: warning: creating a DT_TEXTREL in a shared object\n"));
break;
}
}
return NULL;
}
-/* Return the global debug definition section. */
+/* Return the debug definition section. */
static asection *
elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+ Elf_Internal_Sym *sym)
{
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
- return h->root.u.def.section;
+ if (h != NULL)
+ {
+ /* Return the global debug definition section. */
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+ return h->root.u.def.section;
+ }
+ else
+ {
+ /* Return the local debug definition section. */
+ asection *isec = bfd_section_from_elf_index (sec->owner,
+ sym->st_shndx);
+ if ((isec->flags & SEC_DEBUGGING) != 0)
+ return isec;
+ }
return NULL;
}
h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
if (h == NULL)
{
- info->callbacks->einfo (_("%F%P: corrupt input: %B\n"),
+ info->callbacks->einfo (_("%F%P: corrupt input: %pB\n"),
sec->owner);
return NULL;
}
if (info->print_gc_sections && o->size != 0)
/* xgettext:c-format */
- _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
+ _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"),
o, sub);
}
}
if (!bed->can_gc_sections
|| !is_elf_hash_table (info->hash))
{
- _bfd_error_handler(_("Warning: gc-sections option ignored"));
+ _bfd_error_handler(_("warning: gc-sections option ignored"));
return TRUE;
}
}
/* xgettext:c-format */
- _bfd_error_handler (_("%B: %A+%#Lx: No symbol found for INHERIT"),
- abfd, sec, offset);
+ _bfd_error_handler (_("%pB: %pA+%#" PRIx64 ": no symbol found for INHERIT"),
+ abfd, sec, (uint64_t) offset);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
/* Called from check_relocs to record the existence of a VTENTRY reloc. */
bfd_boolean
-bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
+bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
struct elf_link_hash_entry *h,
bfd_vma addend)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
unsigned int log_file_align = bed->s->log_file_align;
+ if (!h)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: section '%pA': corrupt VTENTRY entry"),
+ abfd, sec);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
if (!h->u2.vtable)
{
h->u2.vtable = ((struct elf_link_virtual_table_entry *)
if (!tf->valid)
{
info->callbacks->einfo
- (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
+ (_("unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
return FALSE;
}
}