Return reloc_class_ifunc for reloc against IFUNC
elf_XXX_reloc_type_class should return reloc_class_ifunc for relocation against STT_GNU_IFUNC symbol. bfd/ PR ld/18841 * elf-bfd.h (elf_link_hash_table): Add dynsym. * elf32-i386.c (elf_i386_reloc_type_class): Return reloc_class_ifunc for relocation against STT_GNU_IFUNC symbol. * elf64-x86-64.c (elf_x86_64_reloc_type_class): Likewise. * elflink.c (_bfd_elf_link_create_dynamic_sections): Set dynsym. (bfd_elf_size_dynsym_hash_dynstr): Use dynsym. (elf_final_link_info): Remove dynsym_sec. (elf_link_output_extsym): Replace dynsym_sec with dynsym. (bfd_elf_final_link): Remove reference to dynsym_sec. Replace dynsym_sec with dynsym. ld/testsuite/ PR ld/18841 * ld-ifunc/ifunc.exp: Add a test for PR ld/18841. * ld-ifunc/pr18841.out: New file. * ld-ifunc/pr18841a.c: Likewise. * ld-ifunc/pr18841b.c: Likewise.
This commit is contained in:
parent
2b4bf6afd4
commit
cae1fbbb7e
10 changed files with 119 additions and 13 deletions
|
@ -5,6 +5,20 @@
|
|||
(elfNN_aarch64_gc_sweep_hook): Likewise.
|
||||
(elfNN_aarch64_check_relocs): Likewise.
|
||||
|
||||
2015-08-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/18841
|
||||
* elf-bfd.h (elf_link_hash_table): Add dynsym.
|
||||
* elf32-i386.c (elf_i386_reloc_type_class): Return
|
||||
reloc_class_ifunc for relocation against STT_GNU_IFUNC symbol.
|
||||
* elf64-x86-64.c (elf_x86_64_reloc_type_class): Likewise.
|
||||
* elflink.c (_bfd_elf_link_create_dynamic_sections): Set dynsym.
|
||||
(bfd_elf_size_dynsym_hash_dynstr): Use dynsym.
|
||||
(elf_final_link_info): Remove dynsym_sec.
|
||||
(elf_link_output_extsym): Replace dynsym_sec with dynsym.
|
||||
(bfd_elf_final_link): Remove reference to dynsym_sec. Replace
|
||||
dynsym_sec with dynsym.
|
||||
|
||||
2015-08-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* bfd/aoutx.h: Replace shared, executable, relocatable and pie
|
||||
|
|
|
@ -595,6 +595,7 @@ struct elf_link_hash_table
|
|||
asection *iplt;
|
||||
asection *irelplt;
|
||||
asection *irelifunc;
|
||||
asection *dynsym;
|
||||
};
|
||||
|
||||
/* Look up an entry in an ELF linker hash table. */
|
||||
|
|
|
@ -4973,10 +4973,27 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
|
|||
dynamic linker, before writing them out. */
|
||||
|
||||
static enum elf_reloc_type_class
|
||||
elf_i386_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
elf_i386_reloc_type_class (const struct bfd_link_info *info,
|
||||
const asection *rel_sec ATTRIBUTE_UNUSED,
|
||||
const Elf_Internal_Rela *rela)
|
||||
{
|
||||
bfd *abfd = info->output_bfd;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
struct elf_link_hash_table *htab = elf_hash_table (info);
|
||||
unsigned long r_symndx = ELF32_R_SYM (rela->r_info);
|
||||
Elf_Internal_Sym sym;
|
||||
|
||||
if (htab->dynsym == NULL
|
||||
|| !bed->s->swap_symbol_in (abfd,
|
||||
(htab->dynsym->contents
|
||||
+ r_symndx * sizeof (Elf32_External_Sym)),
|
||||
0, &sym))
|
||||
abort ();
|
||||
|
||||
/* Check relocation against STT_GNU_IFUNC symbol. */
|
||||
if (ELF32_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
|
||||
return reloc_class_ifunc;
|
||||
|
||||
switch (ELF32_R_TYPE (rela->r_info))
|
||||
{
|
||||
case R_386_RELATIVE:
|
||||
|
|
|
@ -5464,10 +5464,27 @@ elf_x86_64_finish_local_dynamic_symbol (void **slot, void *inf)
|
|||
dynamic linker, before writing them out. */
|
||||
|
||||
static enum elf_reloc_type_class
|
||||
elf_x86_64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
elf_x86_64_reloc_type_class (const struct bfd_link_info *info,
|
||||
const asection *rel_sec ATTRIBUTE_UNUSED,
|
||||
const Elf_Internal_Rela *rela)
|
||||
{
|
||||
bfd *abfd = info->output_bfd;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
|
||||
unsigned long r_symndx = htab->r_sym (rela->r_info);
|
||||
Elf_Internal_Sym sym;
|
||||
|
||||
if (htab->elf.dynsym == NULL
|
||||
|| !bed->s->swap_symbol_in (abfd,
|
||||
(htab->elf.dynsym->contents
|
||||
+ r_symndx * bed->s->sizeof_sym),
|
||||
0, &sym))
|
||||
abort ();
|
||||
|
||||
/* Check relocation against STT_GNU_IFUNC symbol. */
|
||||
if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
|
||||
return reloc_class_ifunc;
|
||||
|
||||
switch ((int) ELF32_R_TYPE (rela->r_info))
|
||||
{
|
||||
case R_X86_64_RELATIVE:
|
||||
|
|
|
@ -279,6 +279,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
|||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
|
||||
return FALSE;
|
||||
elf_hash_table (info)->dynsym = s;
|
||||
|
||||
s = bfd_make_section_anyway_with_flags (abfd, ".dynstr",
|
||||
flags | SEC_READONLY);
|
||||
|
@ -6545,7 +6546,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
|
|||
the final symbol table, because until then we do not know the
|
||||
correct value to give the symbols. We built the .dynstr
|
||||
section as we went along in elf_link_add_object_symbols. */
|
||||
s = bfd_get_linker_section (dynobj, ".dynsym");
|
||||
s = elf_hash_table (info)->dynsym;
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->size = dynsymcount * bed->s->sizeof_sym;
|
||||
|
||||
|
@ -7541,8 +7542,6 @@ struct elf_final_link_info
|
|||
bfd *output_bfd;
|
||||
/* Symbol string table. */
|
||||
struct elf_strtab_hash *symstrtab;
|
||||
/* .dynsym section. */
|
||||
asection *dynsym_sec;
|
||||
/* .hash section. */
|
||||
asection *hash_sec;
|
||||
/* symbol version section (.gnu.version). */
|
||||
|
@ -9314,7 +9313,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
|||
/* If this symbol should be put in the .dynsym section, then put it
|
||||
there now. We already know the symbol index. We also fill in
|
||||
the entry in the .hash section. */
|
||||
if (flinfo->dynsym_sec != NULL
|
||||
if (elf_hash_table (flinfo->info)->dynsym != NULL
|
||||
&& h->dynindx != -1
|
||||
&& elf_hash_table (flinfo->info)->dynamic_sections_created)
|
||||
{
|
||||
|
@ -9344,7 +9343,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
|||
}
|
||||
|
||||
sym.st_name = h->dynstr_index;
|
||||
esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
|
||||
esym = (elf_hash_table (flinfo->info)->dynsym->contents
|
||||
+ h->dynindx * bed->s->sizeof_sym);
|
||||
if (!check_dynsym (flinfo->output_bfd, &sym))
|
||||
{
|
||||
eoinfo->failed = TRUE;
|
||||
|
@ -10868,13 +10868,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
|||
|
||||
if (! dynamic)
|
||||
{
|
||||
flinfo.dynsym_sec = NULL;
|
||||
flinfo.hash_sec = NULL;
|
||||
flinfo.symver_sec = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
flinfo.dynsym_sec = bfd_get_linker_section (dynobj, ".dynsym");
|
||||
flinfo.hash_sec = bfd_get_linker_section (dynobj, ".hash");
|
||||
/* Note that dynsym_sec can be NULL (on VMS). */
|
||||
flinfo.symver_sec = bfd_get_linker_section (dynobj, ".gnu.version");
|
||||
|
@ -11407,11 +11405,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
|||
symtab_hdr->sh_info = bfd_get_symcount (abfd);
|
||||
|
||||
if (dynamic
|
||||
&& flinfo.dynsym_sec != NULL
|
||||
&& flinfo.dynsym_sec->output_section != bfd_abs_section_ptr)
|
||||
&& elf_hash_table (info)->dynsym != NULL
|
||||
&& (elf_hash_table (info)->dynsym->output_section
|
||||
!= bfd_abs_section_ptr))
|
||||
{
|
||||
Elf_Internal_Sym sym;
|
||||
bfd_byte *dynsym = flinfo.dynsym_sec->contents;
|
||||
bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents;
|
||||
long last_local = 0;
|
||||
|
||||
/* Write out the section symbols for the output sections. */
|
||||
|
@ -11484,7 +11483,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
elf_section_data (flinfo.dynsym_sec->output_section)->this_hdr.sh_info =
|
||||
elf_section_data (elf_hash_table (info)->dynsym->output_section)->this_hdr.sh_info =
|
||||
last_local + 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2015-08-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/18841
|
||||
* ld-ifunc/ifunc.exp: Add a test for PR ld/18841.
|
||||
* ld-ifunc/pr18841.out: New file.
|
||||
* ld-ifunc/pr18841a.c: Likewise.
|
||||
* ld-ifunc/pr18841b.c: Likewise.
|
||||
|
||||
2015-08-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/18801
|
||||
|
|
|
@ -472,6 +472,14 @@ run_cc_link_tests [list \
|
|||
{} \
|
||||
"libpr18808.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build libpr18841.so" \
|
||||
"-shared" \
|
||||
"-fPIC -O0 -g" \
|
||||
{ pr18841b.c } \
|
||||
{} \
|
||||
"libpr18841.so" \
|
||||
] \
|
||||
]
|
||||
|
||||
run_ld_link_exec_tests [] [list \
|
||||
|
@ -483,4 +491,12 @@ run_ld_link_exec_tests [] [list \
|
|||
"pr18808" \
|
||||
"pr18808.out" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr18841" \
|
||||
"tmpdir/libpr18841.so" \
|
||||
"" \
|
||||
{ pr18841a.c } \
|
||||
"pr18841" \
|
||||
"pr18841.out" \
|
||||
] \
|
||||
]
|
||||
|
|
1
ld/testsuite/ld-ifunc/pr18841.out
Normal file
1
ld/testsuite/ld-ifunc/pr18841.out
Normal file
|
@ -0,0 +1 @@
|
|||
OK
|
12
ld/testsuite/ld-ifunc/pr18841a.c
Normal file
12
ld/testsuite/ld-ifunc/pr18841a.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern void test(void);
|
||||
|
||||
void zoo(){}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
21
ld/testsuite/ld-ifunc/pr18841b.c
Normal file
21
ld/testsuite/ld-ifunc/pr18841b.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
void foo() __attribute__((ifunc("resolve_foo")));
|
||||
|
||||
static void foo_impl() {}
|
||||
|
||||
extern void abort (void);
|
||||
void test()
|
||||
{
|
||||
void (*pg)(void) = foo;
|
||||
if (pg != foo_impl)
|
||||
abort ();
|
||||
pg();
|
||||
}
|
||||
|
||||
static void* resolve_foo()
|
||||
{
|
||||
extern void zoo(void);
|
||||
|
||||
void (*pz)(void) = zoo;
|
||||
pz();
|
||||
return foo_impl;
|
||||
}
|
Loading…
Reference in a new issue