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;
oldweak = (h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_undefweak);
+ if (bind == STB_GNU_UNIQUE)
+ h->unique_global = 1;
+
/* If a new weak symbol definition comes from a regular file and the
old symbol comes from a dynamic library, we treat the new one as
strong. Similarly, an old weak symbol definition from a regular
about symbols which are defined by one dynamic object and
referenced by another one? */
if (!h->needs_plt
+ && h->type != STT_GNU_IFUNC
&& (h->def_regular
|| !h->def_dynamic
|| (!h->ref_regular
dynobj = elf_hash_table (eif->info)->dynobj;
bed = get_elf_backend_data (dynobj);
-
- if (h->type == STT_GNU_IFUNC
- && (bed->elf_osabi == ELFOSABI_LINUX
- /* GNU/Linux is still using the default value 0. */
- || bed->elf_osabi == ELFOSABI_NONE))
- h->needs_plt = 1;
-
if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
{
eif->failed = TRUE;
unsigned long shlink;
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
- goto error_free_dyn;
+ {
+error_free_dyn:
+ free (dynbuf);
+ goto error_return;
+ }
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
if (elfsec == SHN_BAD)
amt = strlen (fnm) + 1;
anm = bfd_alloc (abfd, amt);
if (anm == NULL)
- {
- error_free_dyn:
- free (dynbuf);
- goto error_return;
- }
+ goto error_free_dyn;
memcpy (anm, fnm, amt);
n->name = anm;
n->by = abfd;
common = bed->common_definition (isym);
bind = ELF_ST_BIND (isym->st_info);
- if (bind == STB_LOCAL)
+ switch (bind)
{
+ case STB_LOCAL:
/* This should be impossible, since ELF requires that all
global symbols follow all local symbols, and that sh_info
point to the first global symbol. Unfortunately, Irix 5
screws this up. */
continue;
- }
- else if (bind == STB_GLOBAL)
- {
+
+ case STB_GLOBAL:
if (isym->st_shndx != SHN_UNDEF && !common)
flags = BSF_GLOBAL;
- }
- else if (bind == STB_WEAK)
- flags = BSF_WEAK;
- else
- {
+ break;
+
+ case STB_WEAK:
+ flags = BSF_WEAK;
+ break;
+
+ case STB_GNU_UNIQUE:
+ flags = BSF_GNU_UNIQUE;
+ break;
+
+ default:
/* Leave it up to the processor backend. */
+ break;
}
if (isym->st_shndx == SHN_UNDEF)
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
*sym_hash = h;
+ h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
new_weakdef = FALSE;
if (dynamic
if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
&& (definition || h->type == STT_NOTYPE))
{
- if (h->type != STT_NOTYPE
- && h->type != ELF_ST_TYPE (isym->st_info)
- && ! type_change_ok)
- (*_bfd_error_handler)
- (_("Warning: type of symbol `%s' changed"
- " from %d to %d in %B"),
- abfd, name, h->type, ELF_ST_TYPE (isym->st_info));
+ unsigned int type = ELF_ST_TYPE (isym->st_info);
+
+ /* Turn an IFUNC symbol from a DSO into a normal FUNC
+ symbol. */
+ if (type == STT_GNU_IFUNC
+ && (abfd->flags & DYNAMIC) != 0)
+ type = STT_FUNC;
+
+ if (h->type != type)
+ {
+ if (h->type != STT_NOTYPE && ! type_change_ok)
+ (*_bfd_error_handler)
+ (_("Warning: type of symbol `%s' changed"
+ " from %d to %d in %B"),
+ abfd, name, h->type, type);
- h->type = ELF_ST_TYPE (isym->st_info);
+ h->type = type;
+ }
}
/* Merge st_other field. */
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;
else
shift = (8 * wordsz) - (start + len);
+ /* FIXME: octets_per_byte. */
x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
#ifdef DEBUG
relocation, (mask << shift),
((relocation & mask) << shift), x);
#endif
+ /* FIXME: octets_per_byte. */
put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
return r;
}
+ (i2e - 1) * sizeof (Elf_Internal_Rela));
count = dynamic_relocs->size / ext_size;
+ if (count == 0)
+ return 0;
sort = bfd_zmalloc (sort_elt * count);
if (sort == NULL)
}
erel = o->contents;
erelend = o->contents + o->size;
+ /* FIXME: octets_per_byte. */
p = sort + o->output_offset / ext_size * sort_elt;
while (erel < erelend)
erel = o->contents;
erelend = o->contents + o->size;
+ /* FIXME: octets_per_byte. */
p = sort + o->output_offset / ext_size * sort_elt;
while (erel < erelend)
{
sym.st_other = h->other;
if (h->forced_local)
sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+ else if (h->unique_global)
+ sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
else if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak)
sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
/* 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->def_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)))
|| ELF_ST_BIND (sym.st_info) == STB_WEAK))
{
int bindtype;
+ unsigned int type = ELF_ST_TYPE (sym.st_info);
+
+ /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */
+ if (type == STT_GNU_IFUNC)
+ type = STT_FUNC;
if (h->ref_regular_nonweak)
bindtype = STB_GLOBAL;
else
bindtype = STB_WEAK;
- sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+ sym.st_info = ELF_ST_INFO (bindtype, type);
}
/* If this is a symbol defined in a dynamic library, don't use the
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
break;
default:
{
+ /* FIXME: octets_per_byte. */
if (! (o->flags & SEC_EXCLUDE)
&& ! (o->output_section->flags & SEC_NEVER_LOAD)
&& ! bfd_set_section_contents (output_bfd, o->output_section,
offset &= ~(bfd_vma) 0 << s->alignment_power;
s->output_offset = offset;
sections[n]->offset = offset;
+ /* FIXME: octets_per_byte. */
offset += sections[n]->size;
}
!= SHT_STRTAB)
|| strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
{
+ /* FIXME: octets_per_byte. */
if (! bfd_set_section_contents (abfd, o->output_section,
o->contents,
(file_ptr) o->output_offset,
return reloc_sec;
}
-
-/* Returns the name of the ifunc using dynamic reloc section associated with SEC. */
-#define IFUNC_INFIX ".ifunc"
-
-static const char *
-get_ifunc_reloc_section_name (bfd * abfd,
- asection * sec)
-{
- const char * dot;
- char * name;
- const char * base_name;
- unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
- unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
-
- base_name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
- if (base_name == NULL)
- return NULL;
-
- dot = strchr (base_name + 1, '.');
- name = bfd_alloc (abfd, strlen (base_name) + strlen (IFUNC_INFIX) + 1);
- sprintf (name, "%.*s%s%s", (int)(dot - base_name), base_name, IFUNC_INFIX, dot);
-
- return name;
-}
-
-/* Like _bfd_elf_make_dynamic_reloc_section but it creates a
- section for holding relocs against symbols with the STT_GNU_IFUNC
- type. The section is attached to the OWNER bfd but it is created
- with a name based on SEC from ABFD. */
-
-asection *
-_bfd_elf_make_ifunc_reloc_section (bfd * abfd,
- asection * sec,
- bfd * owner,
- unsigned int align)
-{
- asection * reloc_sec = elf_section_data (sec)->indirect_relocs;
-
- if (reloc_sec == NULL)
- {
- const char * name = get_ifunc_reloc_section_name (abfd, sec);
-
- if (name == NULL)
- return NULL;
-
- reloc_sec = bfd_get_section_by_name (owner, name);
-
- if (reloc_sec == NULL)
- {
- flagword flags;
-
- flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
-
- reloc_sec = bfd_make_section_with_flags (owner, name, flags);
-
- if (reloc_sec != NULL
- && ! bfd_set_section_alignment (owner, reloc_sec, align))
- reloc_sec = NULL;
- }
-
- elf_section_data (sec)->indirect_relocs = reloc_sec;
- }
-
- return reloc_sec;
-}