#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;
hash_table = elf_hash_table (info);
if (hash_table->dynobj == NULL)
- hash_table->dynobj = abfd;
+ {
+ /* We may not set dynobj, an input file holding linker created
+ dynamic sections to abfd, which may be a dynamic object with
+ its own dynamic sections. We need to find a normal input file
+ to hold linker created sections if possible. */
+ if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0)
+ {
+ bfd *ibfd;
+ for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
+ if ((ibfd->flags
+ & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+ {
+ abfd = ibfd;
+ break;
+ }
+ }
+ hash_table->dynobj = abfd;
+ }
if (hash_table->dynstr == NULL)
{
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;
}
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,
&dynsymcount);
- /* There is an unused NULL entry at the head of the table which
- we must account for in our count. We always create the dynsym
- section, even if it is empty, with dynamic sections. */
- if (elf_hash_table (info)->dynamic_sections_created)
- ++dynsymcount;
+ /* There is an unused NULL entry at the head of the table which we
+ must account for in our count even if the table is empty since it
+ is intended for the mandatory DT_SYMTAB tag (.dynsym section) in
+ .dynamic section. */
+ dynsymcount++;
elf_hash_table (info)->dynsymcount = dynsymcount;
return dynsymcount;
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);
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);
{
/* 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++)
{
bfd_boolean old_weak;
bfd_boolean override;
bfd_boolean common;
+ bfd_boolean discarded;
unsigned int old_alignment;
bfd *old_bfd;
bfd_boolean matched;
sec = NULL;
value = isym->st_value;
common = bed->common_definition (isym);
+ discarded = FALSE;
bind = ELF_ST_BIND (isym->st_info);
switch (bind)
/* Symbols from discarded section are undefined. We keep
its visibility. */
sec = bfd_und_section_ptr;
+ discarded = TRUE;
isym->st_shndx = SHN_UNDEF;
}
else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
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. */
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ /* Setting the index to -3 tells elf_link_output_extsym that
+ this symbol is defined in a discarded section. */
+ if (discarded)
+ h->indx = -3;
+
*sym_hash = h;
new_weak = (flags & BSF_WEAK) != 0;
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)
/* Work out the size of the symbol version section. */
s = bfd_get_linker_section (dynobj, ".gnu.version");
BFD_ASSERT (s != NULL);
- if (dynsymcount != 0
- && (s->flags & SEC_EXCLUDE) == 0)
+ if ((s->flags & SEC_EXCLUDE) == 0)
{
s->size = dynsymcount * sizeof (Elf_External_Versym);
s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
BFD_ASSERT (s != NULL);
s->size = dynsymcount * bed->s->sizeof_sym;
- if (dynsymcount != 0)
- {
- s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
- if (s->contents == NULL)
- return FALSE;
+ s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+ if (s->contents == NULL)
+ return FALSE;
- /* The first entry in .dynsym is a dummy symbol.
- Clear all the section syms, in case we don't output them all. */
- ++section_sym_count;
- memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
- }
+ /* The first entry in .dynsym is a dummy symbol. Clear all the
+ section syms, in case we don't output them all. */
+ ++section_sym_count;
+ memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
elf_hash_table (info)->bucketcount = 0;
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 *);
struct elf_link_sort_rela *sq;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
int i2e = bed->s->int_rels_per_ext_rel;
+ unsigned int opb = bfd_octets_per_byte (abfd);
void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
struct bfd_link_order *lo;
bfd_boolean use_rela_initialised = FALSE;
/* This is just here to stop gcc from complaining.
- It's initialization checking code is not perfect. */
+ Its initialization checking code is not perfect. */
use_rela = TRUE;
/* Both sections are present. Examine the sizes
/* Section size is only divisible by rela. */
if (use_rela_initialised && (use_rela == FALSE))
{
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+ _bfd_error_handler (_("%B: Unable to sort relocs - "
+ "they are in more than one size"),
+ abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
/* Section size is only divisible by rel. */
if (use_rela_initialised && (use_rela == TRUE))
{
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+ _bfd_error_handler (_("%B: Unable to sort relocs - "
+ "they are in more than one size"),
+ abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
}
else
{
- /* The section size is not divisible by either - something is wrong. */
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are of an unknown size"), abfd);
+ /* The section size is not divisible by either -
+ something is wrong. */
+ _bfd_error_handler (_("%B: 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 == FALSE))
{
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+ _bfd_error_handler (_("%B: Unable to sort relocs - "
+ "they are in more than one size"),
+ abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
/* Section size is only divisible by rel. */
if (use_rela_initialised && (use_rela == TRUE))
{
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+ _bfd_error_handler (_("%B: Unable to sort relocs - "
+ "they are in more than one size"),
+ abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
}
else
{
- /* The section size is not divisible by either - something is wrong. */
- _bfd_error_handler
- (_("%B: Unable to sort relocs - they are of an unknown size"), abfd);
+ /* The section size is not divisible by either -
+ something is wrong. */
+ _bfd_error_handler (_("%B: Unable to sort relocs - "
+ "they are of an unknown size"), abfd);
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
}
erel = o->contents;
erelend = o->contents + o->size;
- /* FIXME: octets_per_byte. */
- p = sort + o->output_offset / ext_size * sort_elt;
+ p = sort + o->output_offset * opb / ext_size * sort_elt;
while (erel < erelend)
{
qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+ if (htab->srelplt && htab->srelplt->output_section == dynamic_relocs)
+ {
+ /* We have plt relocs in .rela.dyn. */
+ sq = (struct elf_link_sort_rela *) sort;
+ for (i = 0; i < count; i++)
+ if (sq[count - i - 1].type != reloc_class_plt)
+ break;
+ if (i != 0 && htab->srelplt->size == i * ext_size)
+ {
+ struct bfd_link_order **plo;
+ /* Put srelplt link_order last. This is so the output_offset
+ set in the next loop is correct for DT_JMPREL. */
+ for (plo = &dynamic_relocs->map_head.link_order; *plo != NULL; )
+ if ((*plo)->type == bfd_indirect_link_order
+ && (*plo)->u.indirect.section == htab->srelplt)
+ {
+ lo = *plo;
+ *plo = lo->next;
+ }
+ else
+ plo = &(*plo)->next;
+ *plo = lo;
+ lo->next = NULL;
+ dynamic_relocs->map_tail.link_order = lo;
+ }
+ }
+
+ p = sort;
for (lo = dynamic_relocs->map_head.link_order; lo != NULL; lo = lo->next)
if (lo->type == bfd_indirect_link_order)
{
erel = o->contents;
erelend = o->contents + o->size;
- /* FIXME: octets_per_byte. */
- p = sort + o->output_offset / ext_size * sort_elt;
+ o->output_offset = (p - sort) / sort_elt * ext_size / opb;
while (erel < erelend)
{
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
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;
&& (!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)
+ return TRUE;
}
/* We should also warn if a forced local symbol is referenced from
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);
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;
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)
{
}
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);
}
{
Elf_Internal_Sym sym;
bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents;
- long last_local = 0;
+
+ o = elf_hash_table (info)->dynsym->output_section;
+ elf_section_data (o)->this_hdr.sh_info
+ = elf_hash_table (info)->local_dynsymcount + 1;
/* Write out the section symbols for the output sections. */
if (bfd_link_pic (info)
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);
}
}
+ 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
case DT_PREINIT_ARRAYSZ:
name = ".preinit_array";
- goto get_size;
+ goto get_out_size;
case DT_INIT_ARRAYSZ:
name = ".init_array";
- goto get_size;
+ goto get_out_size;
case DT_FINI_ARRAYSZ:
name = ".fini_array";
- get_size:
+ get_out_size:
o = bfd_get_section_by_name (abfd, name);
if (o == NULL)
{
- (*_bfd_error_handler)
- (_("%B: could not find output section %s"), abfd, name);
+ _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;
case DT_PREINIT_ARRAY:
name = ".preinit_array";
- goto get_vma;
+ goto get_out_vma;
case DT_INIT_ARRAY:
name = ".init_array";
- goto get_vma;
+ goto get_out_vma;
case DT_FINI_ARRAY:
name = ".fini_array";
- goto get_vma;
+ get_out_vma:
+ o = bfd_get_section_by_name (abfd, name);
+ goto do_vma;
case DT_HASH:
name = ".hash";
case DT_VERSYM:
name = ".gnu.version";
get_vma:
- o = bfd_get_section_by_name (abfd, name);
+ o = bfd_get_linker_section (dynobj, name);
+ do_vma:
if (o == NULL)
{
- (*_bfd_error_handler)
- (_("%B: could not find output section %s"), abfd, name);
+ _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;
}
- dyn.d_un.d_ptr = o->vma;
+ dyn.d_un.d_ptr = o->output_section->vma + o->output_offset;
break;
case DT_REL:
return NULL;
}
+/* For undefined __start_<name> and __stop_<name> symbols, return the
+ first input section matching <name>. Return NULL otherwise. */
+
+asection *
+_bfd_elf_is_start_stop (const struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ asection *s;
+ const char *sec_name;
+
+ if (h->root.type != bfd_link_hash_undefined
+ && h->root.type != bfd_link_hash_undefweak)
+ return NULL;
+
+ s = h->root.u.undef.section;
+ if (s != NULL)
+ {
+ if (s == (asection *) 0 - 1)
+ return NULL;
+ return s;
+ }
+
+ sec_name = NULL;
+ if (strncmp (h->root.root.string, "__start_", 8) == 0)
+ sec_name = h->root.root.string + 8;
+ else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+ sec_name = h->root.root.string + 7;
+
+ if (sec_name != NULL && *sec_name != '\0')
+ {
+ bfd *i;
+
+ for (i = info->input_bfds; i != NULL; i = i->link.next)
+ {
+ s = bfd_get_section_by_name (i, sec_name);
+ if (s != NULL)
+ {
+ h->root.u.undef.section = s;
+ break;
+ }
+ }
+ }
+
+ if (s == NULL)
+ h->root.u.undef.section = (asection *) 0 - 1;
+
+ return s;
+}
+
/* COOKIE->rel describes a relocation against section SEC, which is
a section we've decided to keep. Return the section that contains
the relocation symbol, or NULL if no section contains it. */
if (h->u.weakdef != NULL)
h->u.weakdef->mark = 1;
- if (start_stop != NULL
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak))
+ if (start_stop != NULL)
{
/* To work around a glibc bug, mark all XXX input sections
when there is an as yet undefined reference to __start_XXX
or __stop_XXX symbols. The linker will later define such
symbols for orphan input sections that have a name
representable as a C identifier. */
- const char *sec_name = NULL;
- if (strncmp (h->root.root.string, "__start_", 8) == 0)
- sec_name = h->root.root.string + 8;
- else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
- sec_name = h->root.root.string + 7;
+ asection *s = _bfd_elf_is_start_stop (info, h);
- if (sec_name != NULL && *sec_name != '\0')
+ if (s != NULL)
{
- bfd *i;
-
- for (i = info->input_bfds; i != NULL; i = i->link.next)
- {
- asection *s = bfd_get_section_by_name (i, sec_name);
- if (s != NULL && !s->gc_mark)
- {
- *start_stop = TRUE;
- return s;
- }
- }
+ *start_stop = !s->gc_mark;
+ return s;
}
}
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
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;
}
{
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)