/* ELF linking support for BFD.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "safe-ctype.h"
#include "libiberty.h"
#include "objalloc.h"
+#if BFD_SUPPORTS_PLUGINS
+#include "plugin-api.h"
+#include "plugin.h"
+#endif
/* This struct is used to pass information to routines called via
elf_link_hash_traverse which must return failure. */
struct elf_link_hash_table *htab = elf_hash_table (info);
/* This function may be called more than once. */
- s = bfd_get_linker_section (abfd, ".got");
- if (s != NULL)
+ if (htab->sgot != NULL)
return TRUE;
flags = bed->dynamic_sec_flags;
(SEC_ALLOC | SEC_LINKER_CREATED));
if (s == NULL)
return FALSE;
+ htab->sdynbss = s;
+
+ if (bed->want_dynrelro)
+ {
+ /* Similarly, but for symbols that were originally in read-only
+ sections. */
+ s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
+ (SEC_ALLOC | SEC_READONLY
+ | SEC_HAS_CONTENTS
+ | SEC_LINKER_CREATED));
+ if (s == NULL)
+ return FALSE;
+ htab->sdynrelro = s;
+ }
/* The .rel[a].bss section holds copy relocs. This section is not
normally needed. We need to create it here, though, so that the
be needed, we can discard it later. We will never need this
section when generating a shared object, since they do not use
copy relocs. */
- if (! bfd_link_pic (info))
+ if (bfd_link_executable (info))
{
s = bfd_make_section_anyway_with_flags (abfd,
(bed->rela_plts_and_copies_p
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
+ htab->srelbss = s;
+
+ if (bed->want_dynrelro)
+ {
+ s = (bfd_make_section_anyway_with_flags
+ (abfd, (bed->rela_plts_and_copies_p
+ ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
+ flags | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
+ return FALSE;
+ htab->sreldynrelro = s;
+ }
}
}
struct elf_strtab_hash *dynstr;
char *p;
const char *name;
- bfd_size_type indx;
+ size_t indx;
/* XXX: The ABI draft says the linker must turn hidden and
internal symbols into STB_LOCAL symbols when producing the
if (p != NULL)
*p = ELF_VER_CHR;
- if (indx == (bfd_size_type) -1)
+ if (indx == (size_t) -1)
return FALSE;
h->dynstr_index = indx;
}
if (h == NULL)
return provide;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
if (h->versioned == unknown)
{
/* Set versioned if symbol version is unknown. */
hv->root.u.i.link = (struct bfd_link_hash_entry *) h;
(*bed->elf_backend_copy_indirect_symbol) (info, h, hv);
break;
- case bfd_link_hash_warning:
- abort ();
- break;
+ default:
+ BFD_FAIL ();
+ return FALSE;
}
/* If this symbol is being provided by the linker script, and it is
struct elf_link_local_dynamic_entry *entry;
struct elf_link_hash_table *eht;
struct elf_strtab_hash *dynstr;
- unsigned long dynstr_index;
+ size_t dynstr_index;
char *name;
Elf_External_Sym_Shndx eshndx;
char esym[sizeof (Elf64_External_Sym)];
}
dynstr_index = _bfd_elf_strtab_add (dynstr, name, FALSE);
- if (dynstr_index == (unsigned long) -1)
+ if (dynstr_index == (size_t) -1)
return 0;
entry->isym.st_name = dynstr_index;
for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
p->dynindx = ++dynsymcount;
}
+ elf_hash_table (info)->local_dynsymcount = dynsymcount;
elf_link_hash_traverse (elf_hash_table (info),
elf_link_renumber_hash_table_dynsyms,
oldfunc = (h->type != STT_NOTYPE
&& bed->is_function_type (h->type));
- /* When we try to create a default indirect symbol from the dynamic
- definition with the default version, we skip it if its type and
- the type of existing regular definition mismatch. */
+ /* If creating a default indirect symbol ("foo" or "foo@") from a
+ dynamic versioned definition ("foo@@") skip doing so if there is
+ an existing regular definition with a different type. We don't
+ want, for example, a "time" variable in the executable overriding
+ a "time" function in a shared library. */
if (pold_alignment == NULL
&& newdyn
&& newdef
&& !olddyn
- && (((olddef || h->root.type == bfd_link_hash_common)
- && ELF_ST_TYPE (sym->st_info) != h->type
- && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
- && h->type != STT_NOTYPE
- && !(newfunc && oldfunc))
- || (olddef
- && ((h->type == STT_GNU_IFUNC)
- != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))))
+ && (olddef || h->root.type == bfd_link_hash_common)
+ && ELF_ST_TYPE (sym->st_info) != h->type
+ && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+ && h->type != STT_NOTYPE
+ && !(newfunc && oldfunc))
{
*skip = TRUE;
return TRUE;
}
if (tdef && ntdef)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: TLS definition in %B section %A "
"mismatches non-TLS definition in %B section %A"),
tbfd, tsec, ntbfd, ntsec, h->root.root.string);
else if (!tdef && !ntdef)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: TLS reference in %B "
"mismatches non-TLS reference in %B"),
tbfd, ntbfd, h->root.root.string);
else if (tdef)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: TLS definition in %B section %A "
"mismatches non-TLS reference in %B"),
tbfd, tsec, ntbfd, h->root.root.string);
else
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: TLS reference in %B "
"mismatches non-TLS definition in %B section %A"),
tbfd, ntbfd, ntsec, h->root.root.string);
the old symbol override the new one as normally happens with
symbols defined in dynamic objects. */
- if (! ((*info->callbacks->multiple_common)
- (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
- return FALSE;
-
+ (*info->callbacks->multiple_common) (info, &h->root, abfd,
+ bfd_link_hash_common, sym->st_size);
if (sym->st_size > h->size)
h->size = sym->st_size;
/* It would be best if we could set the hash table entry to a
common symbol, but we don't know what to use for the section
or the alignment. */
- if (! ((*info->callbacks->multiple_common)
- (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
- return FALSE;
+ (*info->callbacks->multiple_common) (info, &h->root, abfd,
+ bfd_link_hash_common, sym->st_size);
/* If the presumed common symbol in the dynamic object is
larger, pretend that the new symbol has its size. */
if (skip)
goto nondefault;
+ if (hi->def_regular)
+ {
+ /* If the undecorated symbol will have a version added by a
+ script different to H, then don't indirect to/from the
+ undecorated symbol. This isn't ideal because we may not yet
+ have seen symbol versions, if given by a script on the
+ command line rather than via --version-script. */
+ if (hi->verinfo.vertree == NULL && info->version_info != NULL)
+ {
+ bfd_boolean hide;
+
+ hi->verinfo.vertree
+ = bfd_find_version_for_sym (info->version_info,
+ hi->root.root.string, &hide);
+ if (hi->verinfo.vertree != NULL && hide)
+ {
+ (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+ goto nondefault;
+ }
+ }
+ if (hi->verinfo.vertree != NULL
+ && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0)
+ goto nondefault;
+ }
+
if (! override)
{
/* Add the default symbol if not performing a relocatable link. */
overridden by a versioned definition. */
if (hi->root.type != bfd_link_hash_defined
&& hi->root.type != bfd_link_hash_defweak)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unexpected redefinition of indirect versioned symbol `%s'"),
abfd, shortname);
}
const struct elf_backend_data *bed;
struct elf_info_failed eif;
char *p;
- bfd_size_type amt;
sinfo = (struct elf_info_failed *) data;
info = sinfo->info;
if (h->dynindx == -1)
return TRUE;
- amt = sizeof *t;
- t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt);
+ t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd,
+ sizeof *t);
if (t == NULL)
{
sinfo->failed = TRUE;
{
/* We could not find the version for a symbol when
generating a shared archive. Return an error. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: version node not found for symbol %s"),
info->output_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
{
if ((size_t) r_symndx >= nsyms)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
" for offset 0x%lx in section `%A'"),
abfd, sec,
}
else if (r_symndx != STN_UNDEF)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
" when the object file has no symbol table"),
abfd, sec,
}
else
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: relocation size mismatch in %B section %A"),
output_bfd, input_section->owner, input_section);
bfd_set_error (bfd_error_wrong_format);
&& (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
h->def_regular = 1;
+ /* 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)
+ (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
+ /* A hidden versioned symbol in executable should be forced local if
+ it is is locally defined, not referenced by shared library and not
+ exported. */
+ else if (bfd_link_executable (eif->info)
+ && h->versioned == versioned_hidden
+ && !eif->info->export_dynamic
+ && !h->dynamic
+ && !h->ref_dynamic
+ && h->def_regular)
+ (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
/* If -Bsymbolic was used (which means to bind references to global
symbols to the definition within the shared object), and this
symbol was defined in a regular object, then it actually doesn't
need a PLT entry. Likewise, if the symbol has non-default
visibility. If the symbol has hidden or internal visibility, we
will force it local. */
- if (h->needs_plt
- && bfd_link_pic (eif->info)
- && is_elf_hash_table (eif->info->hash)
- && (SYMBOLIC_BIND (eif->info, h)
- || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- && h->def_regular)
+ else if (h->needs_plt
+ && bfd_link_pic (eif->info)
+ && is_elf_hash_table (eif->info->hash)
+ && (SYMBOLIC_BIND (eif->info, h)
+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ && h->def_regular)
{
bfd_boolean force_local;
(*bed->elf_backend_hide_symbol) (eif->info, h, force_local);
}
- /* 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)
- (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
-
/* If this is a weak defined symbol in a dynamic object, and we know
the real definition in the dynamic object, copy interesting flags
over to the real definition. */
if (h->size == 0
&& h->type == STT_NOTYPE
&& !h->needs_plt)
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: type and size of dynamic symbol `%s' are not defined"),
h->root.root.string);
elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
{
Elf_Internal_Shdr * hdr;
- bfd_size_type symcount;
- bfd_size_type extsymcount;
- bfd_size_type extsymoff;
+ size_t symcount;
+ size_t extsymcount;
+ size_t extsymoff;
Elf_Internal_Sym *isymbuf;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
if (abfd == NULL)
return FALSE;
- /* Return FALSE if the object has been claimed by plugin. */
- if (abfd->plugin_format == bfd_plugin_yes)
- return FALSE;
-
if (! bfd_check_format (abfd, bfd_object))
return FALSE;
- /* Select the appropriate symbol table. */
- if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+ /* Select the appropriate symbol table. If we don't know if the
+ object file is an IR object, give linker LTO plugin a chance to
+ get the correct symbol table. */
+ if (abfd->plugin_format == bfd_plugin_yes
+#if BFD_SUPPORTS_PLUGINS
+ || (abfd->plugin_format == bfd_plugin_unknown
+ && bfd_link_plugin_object_p (abfd))
+#endif
+ )
+ {
+ /* Use the IR symbol table if the object has been claimed by
+ plugin. */
+ abfd = abfd->plugin_dummy_bfd;
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ }
+ else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
hdr = &elf_tdata (abfd)->symtab_hdr;
else
hdr = &elf_tdata (abfd)->dynsymtab_hdr;
bfd_boolean do_it)
{
struct elf_link_hash_table *hash_table;
- bfd_size_type strindex;
+ size_t strindex;
if (!_bfd_elf_link_create_dynstrtab (abfd, info))
return -1;
hash_table = elf_hash_table (info);
strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
- if (strindex == (bfd_size_type) -1)
+ if (strindex == (size_t) -1)
return -1;
if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1)
{
asection *s;
bfd_byte *p;
- bfd_size_type i;
+ size_t i;
Elf_Internal_Verdef def;
Elf_Internal_Verdaux defaux;
{
asection *s;
bfd_byte *p;
- bfd_size_type i;
+ size_t i;
Elf_Internal_Verneed need;
Elf_Internal_Vernaux needaux;
{
Elf_Internal_Ehdr *ehdr;
Elf_Internal_Shdr *hdr;
- bfd_size_type symcount;
- bfd_size_type extsymcount;
- bfd_size_type extsymoff;
+ size_t symcount;
+ size_t extsymcount;
+ size_t extsymoff;
struct elf_link_hash_entry **sym_hash;
bfd_boolean dynamic;
Elf_External_Versym *extversym = NULL;
Elf_External_Versym *ever;
struct elf_link_hash_entry *weaks;
struct elf_link_hash_entry **nondeflt_vers = NULL;
- bfd_size_type nondeflt_vers_cnt = 0;
+ size_t nondeflt_vers_cnt = 0;
Elf_Internal_Sym *isymbuf = NULL;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
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;
+ void *old_strtab = NULL;
size_t tabsize = 0;
asection *s;
bfd_boolean just_syms;
|| (bed->elf_machine_alt2 != 0
&& ehdr->e_machine == bed->elf_machine_alt2)))
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
ehdr->e_machine, abfd, bed->elf_machine_code);
const char *soname = NULL;
char *audit = NULL;
struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+ const Elf_Internal_Phdr *phdr;
int ret;
/* ld --just-symbols and dynamic objects don't mix very well.
*pn = rpath;
}
+ /* If we have a PT_GNU_RELRO program header, mark as read-only
+ 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)
+ if (phdr->p_type == PT_GNU_RELRO)
+ {
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_ALLOC) != 0
+ && s->vma >= phdr->p_vaddr
+ && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz)
+ s->flags |= SEC_READONLY;
+ break;
+ }
+
/* We do not want to include any of the sections in a dynamic
object in the output file. We hack by simply clobbering the
list of sections in the BFD. This could be handled more
{
/* We store a pointer to the hash table entry for each
external symbol. */
- amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+ amt = extsymcount;
+ amt *= 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;
old_table = htab->root.table.table;
old_size = htab->root.table.size;
old_count = htab->root.table.count;
- old_dynsymcount = htab->dynsymcount;
- old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);
+ old_strtab = _bfd_elf_strtab_save (htab->dynstr);
+ if (old_strtab == NULL)
+ goto error_free_vers;
for (i = 0; i < htab->root.table.size; i++)
{
if (verstr == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: %s: invalid version %u (max %d)"),
abfd, name, vernum,
elf_tdata (abfd)->cverdefs);
}
if (verstr == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: %s: invalid needed version %d"),
abfd, name, vernum);
bfd_set_error (bfd_error_bad_value);
(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;
+
h = *sym_hash;
/* We need to make sure that indirect symbol dynamic flags are
updated. */
symbol_align = ffs (h->root.u.def.value) - 1;
if (h->root.u.def.section->owner != NULL
- && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+ && (h->root.u.def.section->owner->flags
+ & (DYNAMIC | BFD_PLUGIN)) == 0)
{
normal_align = h->root.u.def.section->alignment_power;
if (normal_align > symbol_align)
{
/* PR binutils/2735 */
if (normal_bfd == NULL)
- (*_bfd_error_handler)
+ _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"),
common_bfd, h->root.u.def.section,
1 << common_align, name, 1 << normal_align);
else
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: alignment %u of symbol `%s' in %B"
" is smaller than %u in %B"),
normal_bfd, common_bfd,
if (h->size != 0
&& h->size != isym->st_size
&& ! size_change_ok)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: size of symbol `%s' changed"
" from %lu in %B to %lu in %B"),
old_bfd, abfd,
if (h->type != type)
{
if (h->type != STT_NOTYPE && ! type_change_ok)
- (*_bfd_error_handler)
+ /* xgettext:c-format */
+ _bfd_error_handler
(_("Warning: type of symbol `%s' changed"
" from %d to %d in %B"),
abfd, name, h->type, type);
if (old_bfd != NULL
&& (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: undefined reference to symbol '%s'"),
old_bfd, name);
bfd_set_error (bfd_error_missing_dso);
memcpy (htab->root.table.table, old_tab, tabsize);
htab->root.undefs = old_undefs;
htab->root.undefs_tail = old_undefs_tail;
- _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
+ _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
+ free (old_strtab);
+ old_strtab = NULL;
for (i = 0; i < htab->root.table.size; i++)
{
struct bfd_hash_entry *p;
h = (struct elf_link_hash_entry *) p;
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (h->dynindx >= old_dynsymcount
- && h->dynstr_index < old_dynstr_size)
- _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
/* Preserve the maximum alignment and size for common
symbols even if this dynamic lib isn't on DT_NEEDED
such that any relocs against foo become foo@BAR. */
if (!bfd_link_relocatable (info) && nondeflt_vers != NULL)
{
- bfd_size_type cnt, symidx;
+ size_t cnt, symidx;
for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt)
{
/* Since we have to search the whole symbol list for each weak
defined symbol, search time for N weak defined symbols will be
O(N^2). Binary search will cut it down to O(NlogN). */
- amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+ amt = extsymcount;
+ amt *= sizeof (struct elf_link_hash_entry *);
sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt);
if (sorted_sym_hash == NULL)
goto error_return;
error_free_vers:
if (old_tab != NULL)
free (old_tab);
+ if (old_strtab != NULL)
+ free (old_strtab);
if (nondeflt_vers != NULL)
free (nondeflt_vers);
if (extversym != NULL)
if (!(*info->callbacks
->add_archive_element) (info, element, symdef->name, &element))
- goto error_return;
+ continue;
if (!bfd_link_add_symbols (element, info))
goto error_return;
/* The symbol has no type if specified on the command line. */
h->type = STT_OBJECT;
if (info->stacksize)
- (*_bfd_error_handler) (_("%B: stack size specified and %s set"),
- output_bfd, legacy_symbol);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: stack size specified and %s set"),
+ output_bfd, legacy_symbol);
else if (h->root.u.def.section != bfd_abs_section_ptr)
- (*_bfd_error_handler) (_("%B: %s not absolute"),
- output_bfd, legacy_symbol);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: %s not absolute"),
+ output_bfd, legacy_symbol);
else
info->stacksize = h->root.u.def.value;
}
struct bfd_link_info *info,
asection **sinterpptr)
{
- bfd_size_type soname_indx;
+ size_t soname_indx;
bfd *dynobj;
const struct elf_backend_data *bed;
struct elf_info_failed asvinfo;
*sinterpptr = NULL;
- soname_indx = (bfd_size_type) -1;
+ soname_indx = (size_t) -1;
if (!is_elf_hash_table (info->hash))
return TRUE;
{
soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
soname, TRUE);
- if (soname_indx == (bfd_size_type) -1
+ if (soname_indx == (size_t) -1
|| !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
return FALSE;
}
if (rpath != NULL)
{
- bfd_size_type indx;
+ size_t indx;
bfd_vma tag;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
TRUE);
- if (indx == (bfd_size_type) -1)
+ if (indx == (size_t) -1)
return FALSE;
tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
if (filter_shlib != NULL)
{
- bfd_size_type indx;
+ size_t indx;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
filter_shlib, TRUE);
- if (indx == (bfd_size_type) -1
+ if (indx == (size_t) -1
|| !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
return FALSE;
}
for (p = auxiliary_filters; *p != NULL; p++)
{
- bfd_size_type indx;
+ size_t indx;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
*p, TRUE);
- if (indx == (bfd_size_type) -1
+ if (indx == (size_t) -1
|| !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
return FALSE;
}
if (audit != NULL)
{
- bfd_size_type indx;
+ size_t indx;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
TRUE);
- if (indx == (bfd_size_type) -1
+ if (indx == (size_t) -1
|| !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
return FALSE;
}
if (depaudit != NULL)
{
- bfd_size_type indx;
+ size_t indx;
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
TRUE);
- if (indx == (bfd_size_type) -1
+ if (indx == (size_t) -1
|| !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
return FALSE;
}
for (d = t->globals.list; d != NULL; d = d->next)
if (d->literal && !d->symver && !d->script)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%s: undefined version: %s"),
d->pattern, t->name);
all_defined = FALSE;
if (elf_section_data (o)->this_hdr.sh_type
== SHT_PREINIT_ARRAY)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: .preinit_array section is not allowed in DSO"),
sub);
break;
+ sizeof (Elf_External_Verdaux));
}
- if (soname_indx != (bfd_size_type) -1)
+ if (soname_indx != (size_t) -1)
{
_bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
soname_indx);
}
else
{
- bfd_size_type indx;
+ size_t indx;
name = lbasename (output_bfd->filename);
def.vd_hash = bfd_elf_hash (name);
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
name, FALSE);
- if (indx == (bfd_size_type) -1)
+ if (indx == (size_t) -1)
return FALSE;
defaux.vda_name = indx;
}
{
unsigned int caux;
Elf_Internal_Vernaux *a;
- bfd_size_type indx;
+ size_t indx;
caux = 0;
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
? elf_dt_name (t->vn_bfd)
: lbasename (t->vn_bfd->filename),
FALSE);
- if (indx == (bfd_size_type) -1)
+ if (indx == (size_t) -1)
return FALSE;
t->vn_file = indx;
t->vn_aux = sizeof (Elf_External_Verneed);
a->vna_hash = bfd_elf_hash (a->vna_nodename);
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
a->vna_nodename, FALSE);
- if (indx == (bfd_size_type) -1)
+ if (indx == (size_t) -1)
return FALSE;
a->vna_name = indx;
if (a->vna_nextptr == NULL)
struct elf_link_hash_table *htab;
/* Copy down any references that we may have already seen to the
- symbol which just became indirect if DIR isn't a hidden versioned
- symbol. */
+ symbol which just became indirect. */
if (dir->versioned != versioned_hidden)
- {
- dir->ref_dynamic |= ind->ref_dynamic;
- dir->ref_regular |= ind->ref_regular;
- dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
- dir->non_got_ref |= ind->non_got_ref;
- dir->needs_plt |= ind->needs_plt;
- dir->pointer_equality_needed |= ind->pointer_equality_needed;
- }
+ dir->ref_dynamic |= ind->ref_dynamic;
+ dir->ref_regular |= ind->ref_regular;
+ dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+ dir->non_got_ref |= ind->non_got_ref;
+ dir->needs_plt |= ind->needs_plt;
+ dir->pointer_equality_needed |= ind->pointer_equality_needed;
if (ind->root.type != bfd_link_hash_indirect)
return;
struct elf_symbuf_head
{
struct elf_symbuf_symbol *ssym;
- bfd_size_type count;
+ size_t count;
unsigned int st_shndx;
};
}
static struct elf_symbuf_head *
-elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf)
+elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf)
{
Elf_Internal_Sym **ind, **indbufend, **indbuf;
struct elf_symbuf_symbol *ssym;
struct elf_symbuf_head *ssymbuf, *ssymhead;
- bfd_size_type i, shndx_count, total_size;
+ size_t i, shndx_count, total_size;
indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf));
if (indbuf == NULL)
ssym->st_other = (*ind)->st_other;
ssymhead->count++;
}
- BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count
+ BFD_ASSERT ((size_t) (ssymhead - ssymbuf) == shndx_count
&& (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf)
== total_size));
bfd *bfd1, *bfd2;
const struct elf_backend_data *bed1, *bed2;
Elf_Internal_Shdr *hdr1, *hdr2;
- bfd_size_type symcount1, symcount2;
+ size_t symcount1, symcount2;
Elf_Internal_Sym *isymbuf1, *isymbuf2;
struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
Elf_Internal_Sym *isym, *isymend;
struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
- bfd_size_type count1, count2, i;
+ size_t count1, count2, i;
unsigned int shndx1, shndx2;
bfd_boolean result;
if (ssymbuf1 != NULL && ssymbuf2 != NULL)
{
/* Optimized faster version. */
- bfd_size_type lo, hi, mid;
+ size_t lo, hi, mid;
struct elf_symbol *symp;
struct elf_symbuf_symbol *ssym, *ssymend;
static void
undefined_reference (const char *reftype, const char *name)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("undefined %s reference in complex symbol: %s"),
reftype, name);
}
case 'S':
symbol_is_section = TRUE;
+ /* Fall through. */
case 's':
++sym;
symlen = strtol (sym, (char **) symp, 10);
static bfd_boolean
elf_link_adjust_relocs (bfd *abfd,
+ asection *sec,
struct bfd_elf_section_reloc_data *reldata,
bfd_boolean sort)
{
(*swap_out) (abfd, irela, erela);
}
+ if (bed->elf_backend_update_relocs)
+ (*bed->elf_backend_update_relocs) (sec, reldata);
+
if (sort && count != 0)
{
bfd_vma (*ext_r_off) (const void *);
elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
{
struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info);
- bfd_size_type amt, i;
+ bfd_size_type amt;
+ size_t i;
const struct elf_backend_data *bed;
bfd_byte *symbuf;
Elf_Internal_Shdr *hdr;
if (flinfo->symshndxbuf)
{
- amt = (sizeof (Elf_External_Sym_Shndx)
- * (bfd_get_symcount (flinfo->output_bfd)));
+ amt = sizeof (Elf_External_Sym_Shndx);
+ amt *= bfd_get_symcount (flinfo->output_bfd);
flinfo->symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
if (flinfo->symshndxbuf == NULL)
{
{
/* The gABI doesn't support dynamic symbols in output sections
beyond 64k. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: Too many sections: %d (>= %d)"),
abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
bfd_set_error (bfd_error_nonrepresentable_section);
case bfd_link_hash_undefined:
case bfd_link_hash_undefweak:
abfd = h->root.u.undef.abfd;
- if ((abfd->flags & DYNAMIC) == 0
+ if (abfd == NULL
+ || (abfd->flags & DYNAMIC) == 0
|| (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) == 0)
return FALSE;
break;
{
bfd *input;
Elf_Internal_Shdr *hdr;
- bfd_size_type symcount;
- bfd_size_type extsymcount;
- bfd_size_type extsymoff;
+ size_t symcount;
+ size_t extsymcount;
+ size_t extsymoff;
Elf_Internal_Shdr *versymhdr;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
long indx;
int ret;
unsigned int type;
- /* A symbol is bound locally if it is forced local or it is locally
- defined, hidden versioned, not referenced by shared library and
- not exported when linking executable. */
- bfd_boolean local_bind = (h->forced_local
- || (bfd_link_executable (flinfo->info)
- && !flinfo->info->export_dynamic
- && !h->dynamic
- && !h->ref_dynamic
- && h->def_regular
- && h->versioned == versioned_hidden));
if (h->root.type == bfd_link_hash_warning)
{
/* Decide whether to output this symbol in this pass. */
if (eoinfo->localsyms)
{
- if (!local_bind)
+ if (!h->forced_local)
return TRUE;
}
else
{
- if (local_bind)
+ if (h->forced_local)
return TRUE;
}
&& (!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 (!(flinfo->info->callbacks->undefined_symbol
- (flinfo->info, h->root.root.string,
- h->ref_regular ? NULL : h->root.u.undef.abfd,
- NULL, 0,
- (flinfo->info->unresolved_syms_in_shared_libs
- == RM_GENERATE_ERROR))))
- {
- bfd_set_error (bfd_error_bad_value);
- eoinfo->failed = TRUE;
- return FALSE;
- }
- }
+ (*flinfo->info->callbacks->undefined_symbol)
+ (flinfo->info, h->root.root.string,
+ h->ref_regular ? NULL : h->root.u.undef.abfd,
+ NULL, 0,
+ flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR);
/* Strip a global symbol defined in a discarded section. */
if (h->indx == -3)
hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
+ /* xgettext:c-format */
msg = _("%B: internal symbol `%s' in %B 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");
else
+ /* xgettext:c-format */
msg = _("%B: local symbol `%s' in %B 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) (msg, flinfo->output_bfd, def_bfd,
- h->root.root.string);
+ _bfd_error_handler (msg, flinfo->output_bfd, def_bfd,
+ h->root.root.string);
bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
input_sec->output_section);
if (sym.st_shndx == SHN_BAD)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: could not find output section %A for input section %A"),
flinfo->output_bfd, input_sec->output_section, input_sec);
bfd_set_error (bfd_error_nonrepresentable_section);
abort ();
}
- if (local_bind)
+ if (h->forced_local)
{
sym.st_info = ELF_ST_INFO (STB_LOCAL, type);
/* Turn off visibility on local symbol. */
const char *msg;
if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED)
+ /* xgettext:c-format */
msg = _("%B: 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");
else
+ /* xgettext:c-format */
msg = _("%B: hidden symbol `%s' isn't defined");
- (*_bfd_error_handler) (msg, flinfo->output_bfd, h->root.root.string);
+ _bfd_error_handler (msg, flinfo->output_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
/* Since there is no version information in the dynamic string,
if there is no version info in symbol version section, we will
have a run-time problem if not linking executable, referenced
- by shared library, not locally defined, or not bound locally.
- */
+ by shared library, or not bound locally. */
if (h->verinfo.verdef == NULL
- && !local_bind
&& (!bfd_link_executable (flinfo->info)
|| h->ref_dynamic
|| !h->def_regular))
if (p && p [1] != '\0')
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: No symbol version section for versioned symbol `%s'"),
flinfo->output_bfd, h->root.root.string);
eoinfo->failed = TRUE;
{
if (o->size != o->reloc_count * address_size)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("error: %B: size of section %A is not "
"multiple of address size"),
input_bfd, o);
char buffer [32];
sprintf_vma (buffer, rel->r_info);
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("error: %B contains a reloc (0x%s) for section %A "
"that references a non-existent global symbol"),
input_bfd, o, buffer);
BFD_ASSERT (r_symndx != STN_UNDEF);
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"),
sym_name, o, input_bfd, sec, sec->owner);
}
else
{
- if (! ((*info->callbacks->unattached_reloc)
- (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
- return FALSE;
+ (*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, NULL, NULL, 0);
indx = 0;
}
}
link_order->u.reloc.p->u.section);
else
sym_name = link_order->u.reloc.p->u.name;
- if (! ((*info->callbacks->reloc_overflow)
- (info, NULL, sym_name, howto->name, addend, NULL,
- NULL, (bfd_vma) 0)))
- {
- free (buf);
- return FALSE;
- }
+ (*info->callbacks->reloc_overflow) (info, NULL, sym_name,
+ howto->name, addend, NULL, NULL,
+ (bfd_vma) 0);
break;
}
= get_elf_backend_data (s->owner);
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);
return 0;
}
if (seen_other && seen_linkorder)
{
if (other_sec && linkorder_sec)
- (*_bfd_error_handler) (_("%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections"),
- o, linkorder_sec,
- linkorder_sec->owner, other_sec,
- other_sec->owner);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%A has both ordered [`%A' in %B] "
+ "and unordered [`%A' in %B] sections"),
+ o, linkorder_sec,
+ linkorder_sec->owner, other_sec,
+ other_sec->owner);
else
- (*_bfd_error_handler) (_("%A has both ordered and unordered sections"),
- o);
+ _bfd_error_handler
+ (_("%A has both ordered and unordered sections"), o);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
return TRUE;
}
+/* Generate an import library in INFO->implib_bfd from symbols in ABFD.
+ Returns TRUE upon success, FALSE otherwise. */
+
+static bfd_boolean
+elf_output_implib (bfd *abfd, struct bfd_link_info *info)
+{
+ bfd_boolean ret = FALSE;
+ bfd *implib_bfd;
+ const struct elf_backend_data *bed;
+ flagword flags;
+ enum bfd_architecture arch;
+ unsigned int mach;
+ asymbol **sympp = NULL;
+ long symsize;
+ long symcount;
+ long src_count;
+ elf_symbol_type *osymbuf;
+
+ implib_bfd = info->out_implib_bfd;
+ bed = get_elf_backend_data (abfd);
+
+ if (!bfd_set_format (implib_bfd, bfd_object))
+ return FALSE;
+
+ flags = bfd_get_file_flags (abfd);
+ flags &= ~HAS_RELOC;
+ if (!bfd_set_start_address (implib_bfd, 0)
+ || !bfd_set_file_flags (implib_bfd, flags))
+ return FALSE;
+
+ /* Copy architecture of output file to import library file. */
+ arch = bfd_get_arch (abfd);
+ mach = bfd_get_mach (abfd);
+ if (!bfd_set_arch_mach (implib_bfd, arch, mach)
+ && (abfd->target_defaulted
+ || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd)))
+ return FALSE;
+
+ /* Get symbol table size. */
+ symsize = bfd_get_symtab_upper_bound (abfd);
+ if (symsize < 0)
+ return FALSE;
+
+ /* Read in the symbol table. */
+ sympp = (asymbol **) xmalloc (symsize);
+ symcount = bfd_canonicalize_symtab (abfd, sympp);
+ if (symcount < 0)
+ goto free_sym_buf;
+
+ /* Allow the BFD backend to copy any private header data it
+ understands from the output BFD to the import library BFD. */
+ if (! bfd_copy_private_header_data (abfd, implib_bfd))
+ goto free_sym_buf;
+
+ /* Filter symbols to appear in the import library. */
+ if (bed->elf_backend_filter_implib_symbols)
+ symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp,
+ symcount);
+ else
+ symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount);
+ if (symcount == 0)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ _bfd_error_handler (_("%B: no symbol found for import library"),
+ implib_bfd);
+ goto free_sym_buf;
+ }
+
+
+ /* Make symbols absolute. */
+ osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
+ sizeof (*osymbuf));
+ for (src_count = 0; src_count < symcount; src_count++)
+ {
+ memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count],
+ sizeof (*osymbuf));
+ osymbuf[src_count].symbol.section = bfd_abs_section_ptr;
+ osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS;
+ osymbuf[src_count].symbol.value += sympp[src_count]->section->vma;
+ osymbuf[src_count].internal_elf_sym.st_value =
+ osymbuf[src_count].symbol.value;
+ sympp[src_count] = &osymbuf[src_count].symbol;
+ }
+
+ bfd_set_symtab (implib_bfd, sympp, symcount);
+
+ /* Allow the BFD backend to copy any private data it understands
+ from the output BFD to the import library BFD. This is done last
+ to permit the routine to look at the filtered symbol table. */
+ if (! bfd_copy_private_bfd_data (abfd, implib_bfd))
+ goto free_sym_buf;
+
+ if (!bfd_close (implib_bfd))
+ goto free_sym_buf;
+
+ ret = TRUE;
+
+free_sym_buf:
+ free (sympp);
+ return ret;
+}
+
static void
elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
{
asection *attr_section = NULL;
bfd_vma attr_size = 0;
const char *std_attrs_section;
+ struct elf_link_hash_table *htab = elf_hash_table (info);
- if (! is_elf_hash_table (info->hash))
+ if (!is_elf_hash_table (htab))
return FALSE;
if (bfd_link_pic (info))
abfd->flags |= DYNAMIC;
- dynamic = elf_hash_table (info)->dynamic_sections_created;
- dynobj = elf_hash_table (info)->dynobj;
+ dynamic = htab->dynamic_sections_created;
+ dynobj = htab->dynobj;
emit_relocs = (bfd_link_relocatable (info)
|| info->emitrelocations);
asection *sec;
sec = p->u.indirect.section;
- esdi = elf_section_data (sec);
/* Mark all sections which are to be included in the
link. This will normally be every section. We need
if (sec->flags & SEC_MERGE)
merged = TRUE;
- if (esdo->this_hdr.sh_type == SHT_REL
- || esdo->this_hdr.sh_type == SHT_RELA)
- /* Some backends use reloc_count in relocation sections
- to count particular types of relocs. Of course,
- reloc sections themselves can't have relocations. */
- reloc_count = 0;
- else if (emit_relocs)
- {
- reloc_count = sec->reloc_count;
- if (bed->elf_backend_count_additional_relocs)
- {
- int c;
- c = (*bed->elf_backend_count_additional_relocs) (sec);
- additional_reloc_count += c;
- }
- }
- else if (bed->elf_backend_count_relocs)
- reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
-
if (sec->rawsize > max_contents_size)
max_contents_size = sec->rawsize;
if (sec->size > max_contents_size)
max_contents_size = sec->size;
- /* We are interested in just local symbols, not all
- symbols. */
if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
&& (sec->owner->flags & DYNAMIC) == 0)
{
size_t sym_count;
+ /* We are interested in just local symbols, not all
+ symbols. */
if (elf_bad_symtab (sec->owner))
sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
/ bed->s->sizeof_sym);
&& elf_symtab_shndx_list (sec->owner) != NULL)
max_sym_shndx_count = sym_count;
+ if (esdo->this_hdr.sh_type == SHT_REL
+ || esdo->this_hdr.sh_type == SHT_RELA)
+ /* Some backends use reloc_count in relocation sections
+ to count particular types of relocs. Of course,
+ reloc sections themselves can't have relocations. */
+ ;
+ else if (emit_relocs)
+ {
+ reloc_count = sec->reloc_count;
+ if (bed->elf_backend_count_additional_relocs)
+ {
+ int c;
+ c = (*bed->elf_backend_count_additional_relocs) (sec);
+ additional_reloc_count += c;
+ }
+ }
+ else if (bed->elf_backend_count_relocs)
+ reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
+
+ esdi = elf_section_data (sec);
+
if ((sec->flags & SEC_RELOC) != 0)
{
size_t ext_size = 0;
}
if (! bfd_link_relocatable (info) && merged)
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_link_sec_merge_syms, abfd);
+ elf_link_hash_traverse (htab, _bfd_elf_link_sec_merge_syms, abfd);
/* Figure out the file positions for everything but the symbol table
and the relocs. We set symcount to force assign_section_numbers
if (max_sym_count < 20)
max_sym_count = 20;
- elf_hash_table (info)->strtabsize = max_sym_count;
+ htab->strtabsize = max_sym_count;
amt = max_sym_count * sizeof (struct elf_sym_strtab);
- elf_hash_table (info)->strtab
- = (struct elf_sym_strtab *) bfd_malloc (amt);
- if (elf_hash_table (info)->strtab == NULL)
+ htab->strtab = (struct elf_sym_strtab *) bfd_malloc (amt);
+ if (htab->strtab == NULL)
goto error_return;
/* The real buffer will be allocated in elf_link_swap_symbols_out. */
flinfo.symshndxbuf
goto error_return;
}
- if (elf_hash_table (info)->tls_sec)
+ if (htab->tls_sec)
{
bfd_vma base, end = 0;
asection *sec;
- for (sec = elf_hash_table (info)->tls_sec;
+ for (sec = htab->tls_sec;
sec && (sec->flags & SEC_THREAD_LOCAL);
sec = sec->next)
{
}
end = sec->vma + size;
}
- base = elf_hash_table (info)->tls_sec->vma;
+ base = htab->tls_sec->vma;
/* Only align end of TLS section if static TLS doesn't have special
alignment requirements. */
if (bed->static_tls_alignment == 1)
- end = align_power (end,
- elf_hash_table (info)->tls_sec->alignment_power);
- elf_hash_table (info)->tls_size = end - base;
+ end = align_power (end, htab->tls_sec->alignment_power);
+ htab->tls_size = end - base;
}
/* Reorder SHF_LINK_ORDER sections. */
}
bfd_set_error (bfd_error_wrong_format);
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: file class %s incompatible with %s"),
sub, iclass, oclass);
}
symtab_hdr->sh_info = bfd_get_symcount (abfd);
if (dynamic
- && elf_hash_table (info)->dynsym != NULL
- && (elf_hash_table (info)->dynsym->output_section
- != bfd_abs_section_ptr))
+ && htab->dynsym != NULL
+ && htab->dynsym->output_section != bfd_abs_section_ptr)
{
Elf_Internal_Sym sym;
- bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents;
- long last_local = 0;
+ bfd_byte *dynsym = htab->dynsym->contents;
+
+ o = htab->dynsym->output_section;
+ elf_section_data (o)->this_hdr.sh_info = htab->local_dynsymcount + 1;
/* Write out the section symbols for the output sections. */
if (bfd_link_pic (info)
- || elf_hash_table (info)->is_relocatable_executable)
+ || htab->is_relocatable_executable)
{
asection *s;
return FALSE;
sym.st_value = s->vma;
dest = dynsym + dynindx * bed->s->sizeof_sym;
- if (last_local < dynindx)
- last_local = dynindx;
bed->s->swap_symbol_out (abfd, &sym, dest, 0);
}
}
/* Write out the local dynsyms. */
- if (elf_hash_table (info)->dynlocal)
+ if (htab->dynlocal)
{
struct elf_link_local_dynamic_entry *e;
- for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ for (e = htab->dynlocal; e ; e = e->next)
{
asection *s;
bfd_byte *dest;
+ e->isym.st_value);
}
- if (last_local < e->dynindx)
- last_local = e->dynindx;
-
dest = dynsym + e->dynindx * bed->s->sizeof_sym;
bed->s->swap_symbol_out (abfd, &sym, dest, 0);
}
}
-
- elf_section_data (elf_hash_table (info)->dynsym->output_section)->this_hdr.sh_info =
- last_local + 1;
}
/* We get the global symbols from the hash table. */
return FALSE;
}
+ if (info->out_implib_bfd && !elf_output_implib (abfd, info))
+ {
+ _bfd_error_handler (_("%B: failed to generate import library"),
+ info->out_implib_bfd);
+ return FALSE;
+ }
+
/* Adjust the relocs to have the correct symbol indices. */
for (o = abfd->sections; o != NULL; o = o->next)
{
sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
if (esdo->rel.hdr != NULL
- && !elf_link_adjust_relocs (abfd, &esdo->rel, sort))
+ && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort))
return FALSE;
if (esdo->rela.hdr != NULL
- && !elf_link_adjust_relocs (abfd, &esdo->rela, sort))
+ && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort))
return FALSE;
/* Set the reloc_count field to 0 to prevent write_relocs from
{
struct elf_link_hash_entry *h;
- h = elf_link_hash_lookup (elf_hash_table (info), name,
- FALSE, FALSE, TRUE);
+ h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
if (h != NULL
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
o = bfd_get_section_by_name (abfd, name);
if (o == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("could not find section %s"), name);
goto error_return;
}
if (o->size == 0)
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: %s section has zero size"), name);
dyn.d_un.d_val = o->size;
break;
do_vma:
if (o == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("could not find section %s"), name);
goto error_return;
}
if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: section '%s' is being made into a note"), name);
bfd_set_error (bfd_error_nonrepresentable_section);
goto error_return;
}
}
}
+ if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
+ {
+ /* Don't count procedure linkage table relocs in the
+ overall reloc count. */
+ if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+ dyn.d_un.d_val -= htab->srelplt->size;
+ /* If .rela.plt is the first .rela section, exclude
+ it from DT_RELA. */
+ else if (dyn.d_un.d_ptr == (htab->srelplt->output_section->vma
+ + htab->srelplt->output_offset))
+ dyn.d_un.d_ptr += htab->srelplt->size;
+ }
break;
}
bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
created by _bfd_elf_link_create_dynamic_sections. */
continue;
}
- if (elf_hash_table (info)->stab_info.stabstr == o)
+ if (htab->stab_info.stabstr == o)
continue;
- if (elf_hash_table (info)->eh_info.hdr_sec == o)
+ if (htab->eh_info.hdr_sec == o)
continue;
if (strcmp (o->name, ".dynstr") != 0)
{
off = elf_section_data (o->output_section)->this_hdr.sh_offset;
if (bfd_seek (abfd, off, SEEK_SET) != 0
- || ! _bfd_elf_strtab_emit (abfd,
- elf_hash_table (info)->dynstr))
+ || !_bfd_elf_strtab_emit (abfd, htab->dynstr))
goto error_return;
}
}
}
/* If we have optimized stabs strings, output them. */
- if (elf_hash_table (info)->stab_info.stabstr != NULL)
+ if (htab->stab_info.stabstr != NULL)
{
- if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info))
+ if (!_bfd_write_stab_strings (abfd, &htab->stab_info))
goto error_return;
}
o->flags |= SEC_EXCLUDE;
if (info->print_gc_sections && o->size != 0)
+ /* xgettext:c-format */
_bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
/* But we also have to update some of the relocation
&& ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
&& (!bfd_link_executable (info)
+ || info->gc_keep_exported
|| info->export_dynamic
|| (h->dynamic
&& d != NULL
if (h != NULL
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && !bfd_is_abs_section (h->root.u.def.section))
+ && !bfd_is_abs_section (h->root.u.def.section)
+ && !bfd_is_und_section (h->root.u.def.section))
h->root.u.def.section->flags |= SEC_KEEP;
}
}
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;
}
return FALSE;
/* Mark dynamically referenced symbols. */
- if (htab->dynamic_sections_created)
+ if (htab->dynamic_sections_created || info->gc_keep_exported)
elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
/* Grovel through relocs to find out who stays ... */
{
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
struct elf_link_hash_entry **search, *child;
- bfd_size_type extsymcount;
+ size_t extsymcount;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
/* The sh_info field of the symtab header tells us where the
goto win;
}
- (*_bfd_error_handler) ("%B: %A+%lu: No symbol found for INHERIT",
- abfd, sec, (unsigned long) offset);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: %A+%lu: No symbol found for INHERIT"),
+ abfd, sec, (unsigned long) offset);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
for (i = info->input_bfds; i; i = i->link.next)
{
bfd_signed_vma *local_got;
- bfd_size_type j, locsymcount;
+ size_t j, locsymcount;
Elf_Internal_Shdr *symtab_hdr;
if (bfd_get_flavour (i) != bfd_target_elf_flavour)