asection *s;
struct elf_link_hash_entry *h;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- int ptralign;
+ struct elf_link_hash_table *htab = elf_hash_table (info);
/* This function may be called more than once. */
s = bfd_get_section_by_name (abfd, ".got");
if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
return TRUE;
- switch (bed->s->arch_size)
- {
- case 32:
- ptralign = 2;
- break;
-
- case 64:
- ptralign = 3;
- break;
-
- default:
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
flags = bed->dynamic_sec_flags;
+ s = bfd_make_section_with_flags (abfd,
+ (bed->rela_plts_and_copies_p
+ ? ".rela.got" : ".rel.got"),
+ (bed->dynamic_sec_flags
+ | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ htab->srelgot = s;
+
s = bfd_make_section_with_flags (abfd, ".got", flags);
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, ptralign))
+ || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
+ htab->sgot = s;
if (bed->want_got_plt)
{
s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
if (s == NULL
- || !bfd_set_section_alignment (abfd, s, ptralign))
+ || !bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
return FALSE;
+ htab->sgotplt = s;
}
+ /* The first bit of the global offset table is the header. */
+ s->size += bed->got_header_size;
+
if (bed->want_got_sym)
{
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
(or .got.plt) section. We don't do this in the linker script
because we don't want to define the symbol if we are not creating
a global offset table. */
- h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
+ h = _bfd_elf_define_linkage_sym (abfd, info, s,
+ "_GLOBAL_OFFSET_TABLE_");
elf_hash_table (info)->hgot = h;
if (h == NULL)
return FALSE;
}
- /* The first bit of the global offset table is the header. */
- s->size += bed->got_header_size;
-
return TRUE;
}
\f
struct elf_link_hash_entry *h;
asection *s;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_link_hash_table *htab = elf_hash_table (info);
/* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
.rel[a].bss sections. */
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
+ htab->splt = s;
/* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
.plt section. */
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
+ htab->srelplt = s;
if (! _bfd_elf_create_got_section (abfd, info))
return FALSE;
return TRUE;
}
\f
-static struct bfd_elf_version_tree *
-find_version_for_sym (struct bfd_elf_version_tree *verdefs,
- const char *sym_name,
- bfd_boolean *hide)
-{
- struct bfd_elf_version_tree *t;
- struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
-
- local_ver = NULL;
- global_ver = NULL;
- exist_ver = NULL;
- for (t = verdefs; t != NULL; t = t->next)
- {
- if (t->globals.list != NULL)
- {
- struct bfd_elf_version_expr *d = NULL;
-
- while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
- {
- global_ver = t;
- if (d->symver)
- exist_ver = t;
- d->script = 1;
- /* If the match is a wildcard pattern, keep looking for
- a more explicit, perhaps even local, match. */
- if (d->literal)
- break;
- }
-
- if (d != NULL)
- break;
- }
-
- if (t->locals.list != NULL)
- {
- struct bfd_elf_version_expr *d = NULL;
-
- while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
- {
- local_ver = t;
- /* If the match is a wildcard pattern, keep looking for
- a more explicit, perhaps even global, match. */
- if (d->literal)
- {
- /* An exact match overrides a global wildcard. */
- global_ver = NULL;
- break;
- }
- }
-
- if (d != NULL)
- break;
- }
- }
-
- if (global_ver != NULL)
- {
- /* If we already have a versioned symbol that matches the
- node for this symbol, then we don't want to create a
- duplicate from the unversioned symbol. Instead hide the
- unversioned symbol. */
- *hide = exist_ver == global_ver;
- return global_ver;
- }
-
- if (local_ver != NULL)
- {
- *hide = TRUE;
- return local_ver;
- }
-
- return NULL;
-}
-
/* This routine is used to export all defined symbols into the dynamic
symbol table. It is called via elf_link_hash_traverse. */
bfd_boolean hide;
if (eif->verdefs == NULL
- || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+ || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
&& !hide))
{
if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
{
bfd_boolean hide;
- h->verinfo.vertree = find_version_for_sym (sinfo->verdefs,
+ h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
h->root.root.string, &hide);
if (h->verinfo.vertree != NULL && hide)
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
static bfd_boolean
elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
+ Elf_Internal_Ehdr *ehdr;
Elf_Internal_Shdr *hdr;
bfd_size_type symcount;
bfd_size_type extsymcount;
}
}
+ ehdr = elf_elfheader (abfd);
+ if (info->warn_alternate_em
+ && bed->elf_machine_code != ehdr->e_machine
+ && ((bed->elf_machine_alt1 != 0
+ && ehdr->e_machine == bed->elf_machine_alt1)
+ || (bed->elf_machine_alt2 != 0
+ && ehdr->e_machine == bed->elf_machine_alt2)))
+ info->callbacks->einfo
+ (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
+ ehdr->e_machine, abfd, bed->elf_machine_code);
+
/* As a GNU extension, any input sections which are named
.gnu.warning.SYMBOL are treated as warning symbols for the given
symbol. This differs from .gnu.warning sections, which generate
h->type = ELF_ST_TYPE (isym->st_info);
}
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type == STT_GNU_IFUNC)
+ h->needs_plt = 1;
+
/* Merge st_other field. */
elf_merge_st_other (abfd, h, isym, definition, dynamic);
struct elf_link_hash_entry *h,
bfd_boolean force_local)
{
- h->plt = elf_hash_table (info)->init_plt_offset;
- h->needs_plt = 0;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type != STT_GNU_IFUNC)
+ {
+ h->plt = elf_hash_table (info)->init_plt_offset;
+ h->needs_plt = 0;
+ }
if (force_local)
{
h->forced_local = 1;
/* Add a symbol to the output symbol table. */
-static bfd_boolean
+static int
elf_link_output_sym (struct elf_final_link_info *finfo,
const char *name,
Elf_Internal_Sym *elfsym,
{
bfd_byte *dest;
Elf_External_Sym_Shndx *destshndx;
- bfd_boolean (*output_symbol_hook)
+ int (*output_symbol_hook)
(struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
struct elf_link_hash_entry *);
const struct elf_backend_data *bed;
output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
if (output_symbol_hook != NULL)
{
- if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
- return FALSE;
+ int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h);
+ if (ret != 1)
+ return ret;
}
if (name == NULL || *name == '\0')
elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
name, TRUE, FALSE);
if (elfsym->st_name == (unsigned long) -1)
- return FALSE;
+ return 0;
}
if (finfo->symbuf_count >= finfo->symbuf_size)
{
if (! elf_link_flush_output_syms (finfo, bed))
- return FALSE;
+ return 0;
}
dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
destshndx = bfd_realloc (destshndx, amt * 2);
if (destshndx == NULL)
- return FALSE;
+ return 0;
finfo->symshndxbuf = destshndx;
memset ((char *) destshndx + amt, 0, amt);
finfo->shndxbuf_size *= 2;
finfo->symbuf_count += 1;
bfd_get_symcount (finfo->output_bfd) += 1;
- return TRUE;
+ return 1;
}
/* Return TRUE if the dynamic symbol SYM in ABFD is supported. */
Elf_Internal_Sym sym;
asection *input_sec;
const struct elf_backend_data *bed;
+ long indx;
+ int ret;
if (h->root.type == bfd_link_hash_warning)
{
/* Give the processor backend a chance to tweak the symbol value,
and also to finish up anything that needs to be done for this
symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
- forced local syms when non-shared is due to a historical quirk. */
- if ((h->dynindx != -1
- || h->forced_local)
- && ((finfo->info->shared
- && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
- || !h->forced_local)
- && elf_hash_table (finfo->info)->dynamic_sections_created)
+ forced local syms when non-shared is due to a historical quirk.
+ STT_GNU_IFUNC symbol must go through PLT. */
+ if ((h->type == STT_GNU_IFUNC
+ && h->ref_regular
+ && !finfo->info->relocatable)
+ || ((h->dynindx != -1
+ || h->forced_local)
+ && ((finfo->info->shared
+ && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
+ || !h->forced_local)
+ && elf_hash_table (finfo->info)->dynamic_sections_created))
{
if (! ((*bed->elf_backend_finish_dynamic_symbol)
(finfo->output_bfd, finfo->info, h, &sym)))
if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
return TRUE;
- h->indx = bfd_get_symcount (finfo->output_bfd);
-
- if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
+ indx = bfd_get_symcount (finfo->output_bfd);
+ ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h);
+ if (ret == 0)
{
eoinfo->failed = TRUE;
return FALSE;
}
+ else if (ret == 1)
+ h->indx = indx;
+ else if (h->indx == -2)
+ abort();
return TRUE;
}
asection *isec;
const char *name;
Elf_Internal_Sym osym;
+ long indx;
+ int ret;
*pindex = -1;
&& bfd_is_local_label_name (input_bfd, name)))
continue;
- /* If we get here, we are going to output this symbol. */
-
osym = *isym;
/* Adjust the section index for the output file. */
if (osym.st_shndx == SHN_BAD)
return FALSE;
- *pindex = bfd_get_symcount (output_bfd);
-
/* ELF symbols in relocatable files are section relative, but
in executable files they are virtual addresses. Note that
this code assumes that all ELF sections have an associated
}
}
- if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
+ indx = bfd_get_symcount (output_bfd);
+ ret = elf_link_output_sym (finfo, name, &osym, isec, NULL);
+ if (ret == 0)
return FALSE;
+ else if (ret == 1)
+ *pindex = indx;
}
/* Relocate the contents of each section. */
Elf_Internal_Sym sym = isymbuf[symndx];
asection *sec = finfo->sections[symndx]->output_section;
const char *name;
+ long indx;
+ int ret;
name = bfd_elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
sym.st_value += o->output_offset;
- finfo->indices[symndx] = bfd_get_symcount (output_bfd);
- if (! elf_link_output_sym (finfo, name, &sym, o, NULL))
+ indx = bfd_get_symcount (output_bfd);
+ ret = elf_link_output_sym (finfo, name, &sym, o, NULL);
+ if (ret == 0)
return FALSE;
+ else if (ret == 1)
+ finfo->indices[symndx] = indx;
+ else
+ abort ();
}
elf_section_data (osec)->this_hdr.sh_info
= finfo->indices[symndx];
unsigned long shlink;
const char *name;
asection *osec;
+ long indx;
if (finfo->info->strip == strip_all)
{
}
}
- finfo->indices[r_symndx]
- = bfd_get_symcount (output_bfd);
-
- if (! elf_link_output_sym (finfo, name, &sym, sec,
- NULL))
+ indx = bfd_get_symcount (output_bfd);
+ ret = elf_link_output_sym (finfo, name, &sym, sec,
+ NULL);
+ if (ret == 0)
return FALSE;
+ else if (ret == 1)
+ finfo->indices[r_symndx] = indx;
+ else
+ abort ();
}
r_symndx = finfo->indices[r_symndx];
elfsym.st_info = 0;
elfsym.st_other = 0;
elfsym.st_shndx = SHN_UNDEF;
- if (! elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
- NULL))
+ if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
+ NULL) != 1)
goto error_return;
}
elfsym.st_shndx = i;
if (!info->relocatable)
elfsym.st_value = o->vma;
- if (!elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
+ if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1)
goto error_return;
}
}
table, do it now. */
if (bed->elf_backend_output_arch_local_syms)
{
- typedef bfd_boolean (*out_sym_func)
+ typedef int (*out_sym_func)
(void *, const char *, Elf_Internal_Sym *, asection *,
struct elf_link_hash_entry *);
table, do it now. */
if (bed->elf_backend_output_arch_syms)
{
- typedef bfd_boolean (*out_sym_func)
+ typedef int (*out_sym_func)
(void *, const char *, Elf_Internal_Sym *, asection *,
struct elf_link_hash_entry *);
/* This is the first section with this name. Record it. */
if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
- info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
+ info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
}
bfd_boolean