Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5197 → Rev 6324

/contrib/toolchain/binutils/bfd/elf-ifunc.c
1,6 → 1,5
/* ELF STT_GNU_IFUNC support.
Copyright 2009-2013
Free Software Foundation, Inc.
Copyright (C) 2009-2015 Free Software Foundation, Inc.
 
This file is part of BFD, the Binary File Descriptor library.
 
54,7 → 53,7
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
 
if (info->shared)
if (bfd_link_pic (info))
{
/* We need to create .rel[a].ifunc for shared objects. */
const char *rel_sec = (bed->rela_plts_and_copies_p
126,7 → 125,7
But in non-shared executable, the address of its .plt slot may
be used. Pointer equality may not work correctly. PIE should
be used if pointer equality is required here. */
if (!info->shared
if (!bfd_link_pic (info)
&& (h->dynindx != -1
|| info->export_dynamic)
&& h->pointer_equality_needed)
146,7 → 145,7
/* When building shared library, we need to handle the case where it is
marked with regular reference, but not non-GOT reference since the
non-GOT reference bit may not be set here. */
if (info->shared && !h->non_got_ref && h->ref_regular)
if (bfd_link_pic (info) && !h->non_got_ref && h->ref_regular)
for (p = *head; p != NULL; p = p->next)
if (p->count)
{
221,7 → 220,7
 
/* We need dynamic relocation for STT_GNU_IFUNC symbol only when
there is a non-GOT reference in a shared object. */
if (!info->shared
if (!bfd_link_pic (info)
|| !h->non_got_ref)
*head = NULL;
 
253,12 → 252,12
objects at run-time.
We only need to relocate .got entry in shared object. */
if (h->got.refcount <= 0
|| (info->shared
|| (bfd_link_pic (info)
&& (h->dynindx == -1
|| h->forced_local))
|| (!info->shared
|| (!bfd_link_pic (info)
&& !h->pointer_equality_needed)
|| (info->executable && info->shared)
|| bfd_link_pie (info)
|| htab->sgot == NULL)
{
/* Use .got.plt. */
268,9 → 267,134
{
h->got.offset = htab->sgot->size;
htab->sgot->size += got_entry_size;
if (info->shared)
if (bfd_link_pic (info))
htab->srelgot->size += sizeof_reloc;
}
 
return TRUE;
}
 
/* Similar to _bfd_elf_get_synthetic_symtab, optimized for unsorted PLT
entries. PLT is the PLT section. PLT_SYM_VAL is a function pointer
which returns an array of PLT entry symbol values. */
 
long
_bfd_elf_ifunc_get_synthetic_symtab
(bfd *abfd, long symcount ATTRIBUTE_UNUSED,
asymbol **syms ATTRIBUTE_UNUSED, long dynsymcount, asymbol **dynsyms,
asymbol **ret, asection *plt,
bfd_vma *(*get_plt_sym_val) (bfd *, asymbol **, asection *, asection *))
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
asection *relplt;
asymbol *s;
const char *relplt_name;
bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
arelent *p;
long count, i, n;
size_t size;
Elf_Internal_Shdr *hdr;
char *names;
bfd_vma *plt_sym_val;
 
*ret = NULL;
 
if (plt == NULL)
return 0;
 
if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
return 0;
 
if (dynsymcount <= 0)
return 0;
 
relplt_name = bed->relplt_name;
if (relplt_name == NULL)
relplt_name = bed->rela_plts_and_copies_p ? ".rela.plt" : ".rel.plt";
relplt = bfd_get_section_by_name (abfd, relplt_name);
if (relplt == NULL)
return 0;
 
hdr = &elf_section_data (relplt)->this_hdr;
if (hdr->sh_link != elf_dynsymtab (abfd)
|| (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA))
return 0;
 
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
return -1;
 
count = relplt->size / hdr->sh_entsize;
size = count * sizeof (asymbol);
p = relplt->relocation;
for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
{
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
if (p->addend != 0)
{
#ifdef BFD64
size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64);
#else
size += sizeof ("+0x") - 1 + 8;
#endif
}
}
 
plt_sym_val = get_plt_sym_val (abfd, dynsyms, plt, relplt);
if (plt_sym_val == NULL)
return -1;
 
s = *ret = (asymbol *) bfd_malloc (size);
if (s == NULL)
{
free (plt_sym_val);
return -1;
}
 
names = (char *) (s + count);
p = relplt->relocation;
n = 0;
for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
{
size_t len;
bfd_vma addr;
 
addr = plt_sym_val[i];
if (addr == (bfd_vma) -1)
continue;
 
*s = **p->sym_ptr_ptr;
/* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
we are defining a symbol, ensure one of them is set. */
if ((s->flags & BSF_LOCAL) == 0)
s->flags |= BSF_GLOBAL;
s->flags |= BSF_SYNTHETIC;
s->section = plt;
s->value = addr - plt->vma;
s->name = names;
s->udata.p = NULL;
len = strlen ((*p->sym_ptr_ptr)->name);
memcpy (names, (*p->sym_ptr_ptr)->name, len);
names += len;
if (p->addend != 0)
{
char buf[30], *a;
 
memcpy (names, "+0x", sizeof ("+0x") - 1);
names += sizeof ("+0x") - 1;
bfd_sprintf_vma (abfd, buf, p->addend);
for (a = buf; *a == '0'; ++a)
;
len = strlen (a);
memcpy (names, a, len);
names += len;
}
memcpy (names, "@plt", sizeof ("@plt"));
names += sizeof ("@plt");
++s, ++n;
}
 
free (plt_sym_val);
 
return n;
}