x86; Allow IFUNC pointer defined in PDE
If IFUNC symbol is defined in position-dependent executable, we should change it to the normal function and set its address to its PLT entry which should be resolved by R_*_IRELATIVE at run-time. All external references should be resolved to its PLT in executable. bfd/ PR ld/23169 * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Don't issue an error on IFUNC pointer defined in PDE. * elf32-i386.c (elf_i386_finish_dynamic_symbol): Call _bfd_x86_elf_link_fixup_ifunc_symbol. * elf64-x86-64.c (elf_x86_64_finish_dynamic_symbol): Likewise. * elfxx-x86.c (_bfd_x86_elf_link_fixup_ifunc_symbol): New function. * elfxx-x86.h (_bfd_x86_elf_link_fixup_ifunc_symbol): New. ld/ PR ld/23169 * testsuite/ld-ifunc/ifunc-9-i386.d: New file. * testsuite/ld-ifunc/ifunc-9-x86-64.d: Likewise. * testsuite/ld-ifunc/pr23169a.c: Likewise. * testsuite/ld-ifunc/pr23169a.rd: Likewise. * testsuite/ld-ifunc/pr23169b.c: Likewise. * testsuite/ld-ifunc/pr23169b.c: Likewise. * testsuite/ld-ifunc/pr23169c.rd: Likewise. * testsuite/ld-ifunc/pr23169c.rd: Likewise. * testsuite/ld-ifunc/ifunc-9-x86.d: Removed. * testsuite/ld-ifunc/ifunc.exp: Run PR ld/23169 tests.
This commit is contained in:
parent
9bc935ef33
commit
4ec0995016
@ -1,3 +1,15 @@
|
||||
2018-05-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23169
|
||||
* elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Don't issue
|
||||
an error on IFUNC pointer defined in PDE.
|
||||
* elf32-i386.c (elf_i386_finish_dynamic_symbol): Call
|
||||
_bfd_x86_elf_link_fixup_ifunc_symbol.
|
||||
* elf64-x86-64.c (elf_x86_64_finish_dynamic_symbol): Likewise.
|
||||
* elfxx-x86.c (_bfd_x86_elf_link_fixup_ifunc_symbol): New
|
||||
function.
|
||||
* elfxx-x86.h (_bfd_x86_elf_link_fixup_ifunc_symbol): New.
|
||||
|
||||
2018-05-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23162
|
||||
|
@ -131,8 +131,15 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
|
||||
the resolved function may be used. But in non-PIC executable,
|
||||
the address of its .plt slot may be used. Pointer equality may
|
||||
not work correctly. PIE or non-PLT reference should be used if
|
||||
pointer equality is required here. */
|
||||
pointer equality is required here.
|
||||
|
||||
If STT_GNU_IFUNC symbol is defined in position-dependent executable,
|
||||
backend should change it to the normal function and set its address
|
||||
to its PLT entry which should be resolved by R_*_IRELATIVE at
|
||||
run-time. All external references should be resolved to its PLT in
|
||||
executable. */
|
||||
if (!need_dynreloc
|
||||
&& !(bfd_link_pde (info) && h->def_regular)
|
||||
&& (h->dynindx != -1
|
||||
|| info->export_dynamic)
|
||||
&& h->pointer_equality_needed)
|
||||
|
@ -3805,6 +3805,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
|
||||
sym->st_value = 0;
|
||||
}
|
||||
|
||||
_bfd_x86_elf_link_fixup_ifunc_symbol (info, htab, h, sym);
|
||||
|
||||
/* Don't generate dynamic GOT relocation against undefined weak
|
||||
symbol in executable. */
|
||||
if (h->got.offset != (bfd_vma) -1
|
||||
|
@ -4147,6 +4147,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
|
||||
sym->st_value = 0;
|
||||
}
|
||||
|
||||
_bfd_x86_elf_link_fixup_ifunc_symbol (info, htab, h, sym);
|
||||
|
||||
/* Don't generate dynamic GOT relocation against undefined weak
|
||||
symbol in executable. */
|
||||
if (h->got.offset != (bfd_vma) -1
|
||||
|
@ -1730,6 +1730,52 @@ _bfd_x86_elf_fixup_symbol (struct bfd_link_info *info,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Change the STT_GNU_IFUNC symbol defined in position-dependent
|
||||
executable into the normal function symbol and set its address
|
||||
to its PLT entry, which should be resolved by R_*_IRELATIVE at
|
||||
run-time. */
|
||||
|
||||
void
|
||||
_bfd_x86_elf_link_fixup_ifunc_symbol (struct bfd_link_info *info,
|
||||
struct elf_x86_link_hash_table *htab,
|
||||
struct elf_link_hash_entry *h,
|
||||
Elf_Internal_Sym *sym)
|
||||
{
|
||||
if (bfd_link_pde (info)
|
||||
&& h->def_regular
|
||||
&& h->dynindx != -1
|
||||
&& h->plt.offset != (bfd_vma) -1
|
||||
&& h->type == STT_GNU_IFUNC
|
||||
&& h->pointer_equality_needed)
|
||||
{
|
||||
asection *plt_s;
|
||||
bfd_vma plt_offset;
|
||||
bfd *output_bfd = info->output_bfd;
|
||||
|
||||
if (htab->plt_second)
|
||||
{
|
||||
struct elf_x86_link_hash_entry *eh
|
||||
= (struct elf_x86_link_hash_entry *) h;
|
||||
|
||||
plt_s = htab->plt_second;
|
||||
plt_offset = eh->plt_second.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
plt_s = htab->elf.splt;
|
||||
plt_offset = h->plt.offset;
|
||||
}
|
||||
|
||||
sym->st_size = 0;
|
||||
sym->st_info = ELF_ST_INFO (ELF_ST_BIND (sym->st_info), STT_FUNC);
|
||||
sym->st_shndx
|
||||
= _bfd_elf_section_from_bfd_section (output_bfd,
|
||||
plt_s->output_section);
|
||||
sym->st_value = (plt_s->output_section->vma
|
||||
+ plt_s->output_offset + plt_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
|
||||
|
||||
bfd_boolean
|
||||
|
@ -674,6 +674,10 @@ extern bfd_boolean _bfd_x86_elf_merge_gnu_properties
|
||||
extern bfd * _bfd_x86_elf_link_setup_gnu_properties
|
||||
(struct bfd_link_info *, struct elf_x86_init_table *);
|
||||
|
||||
extern void _bfd_x86_elf_link_fixup_ifunc_symbol
|
||||
(struct bfd_link_info *, struct elf_x86_link_hash_table *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *sym);
|
||||
|
||||
#define bfd_elf64_mkobject \
|
||||
_bfd_x86_elf_mkobject
|
||||
#define bfd_elf32_mkobject \
|
||||
|
14
ld/ChangeLog
14
ld/ChangeLog
@ -1,3 +1,17 @@
|
||||
2018-05-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23169
|
||||
* testsuite/ld-ifunc/ifunc-9-i386.d: New file.
|
||||
* testsuite/ld-ifunc/ifunc-9-x86-64.d: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169a.c: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169a.rd: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169b.c: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169b.c: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169c.rd: Likewise.
|
||||
* testsuite/ld-ifunc/pr23169c.rd: Likewise.
|
||||
* testsuite/ld-ifunc/ifunc-9-x86.d: Removed.
|
||||
* testsuite/ld-ifunc/ifunc.exp: Run PR ld/23169 tests.
|
||||
|
||||
2018-05-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/23162
|
||||
|
9
ld/testsuite/ld-ifunc/ifunc-9-i386.d
Normal file
9
ld/testsuite/ld-ifunc/ifunc-9-i386.d
Normal file
@ -0,0 +1,9 @@
|
||||
#source: ifunc-9-x86.s
|
||||
#as: --32
|
||||
#ld: -m elf_i386 --export-dynamic
|
||||
#readelf: -r --wide
|
||||
#target: x86_64-*-* i?86-*-*
|
||||
|
||||
Relocation section '.rel.plt' at .*
|
||||
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
|
||||
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
|
9
ld/testsuite/ld-ifunc/ifunc-9-x86-64.d
Normal file
9
ld/testsuite/ld-ifunc/ifunc-9-x86-64.d
Normal file
@ -0,0 +1,9 @@
|
||||
#source: ifunc-9-x86.s
|
||||
#as: --64
|
||||
#ld: -melf_x86_64 --export-dynamic
|
||||
#readelf: -r --wide
|
||||
#target: x86_64-*-*
|
||||
|
||||
Relocation section '.rela.plt' at .*
|
||||
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
|
||||
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
|
@ -1,3 +0,0 @@
|
||||
#ld: --export-dynamic
|
||||
#error: .*dynamic STT_GNU_IFUNC symbol `foo' with pointer equality in `.*.o' can not be used when making an executable; recompile with -fPIE and relink with -pie
|
||||
#target: x86_64-*-* i?86-*-*
|
@ -581,6 +581,76 @@ run_cc_link_tests [list \
|
||||
{} \
|
||||
"libpr18841cn.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build libpr23169a.so" \
|
||||
"-shared" \
|
||||
"-fPIC -O2 -g" \
|
||||
{ pr23169a.c } \
|
||||
{} \
|
||||
"libpr23169a.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build libpr23169b.so" \
|
||||
"-shared -Wl,-z,now" \
|
||||
"-fPIC -O2 -g" \
|
||||
{ pr23169a.c } \
|
||||
{} \
|
||||
"libpr23169b.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169a" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"$NOPIE_CFLAGS -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169a.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169a" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169b" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"-fPIE -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169c.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169b" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169c" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"-fPIE -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169c.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169c" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169d" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"$NOPIE_CFLAGS -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169a.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169d" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169e" \
|
||||
"-pie -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"-fPIE -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169c.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169e" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr23169f" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"-fPIE -O2 -g" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
{{readelf {--dyn-syms} pr23169c.rd} \
|
||||
{readelf {-r -W} pr23169b.rd}} \
|
||||
"pr23169f" \
|
||||
] \
|
||||
]
|
||||
|
||||
run_ld_link_exec_tests [list \
|
||||
@ -632,4 +702,58 @@ run_ld_link_exec_tests [list \
|
||||
"pr18841cn" \
|
||||
"pr18841.out" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169a" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169a" \
|
||||
"pass.out" \
|
||||
"$NOPIE_CFLAGS -O2 -g" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169b" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169b" \
|
||||
"pass.out" \
|
||||
"-fPIE -O2 -g" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169c" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libpr23169a.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169c" \
|
||||
"pass.out" \
|
||||
"-fPIE -O2 -g" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169d" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169d" \
|
||||
"pass.out" \
|
||||
"$NOPIE_CFLAGS -O2 -g" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169e" \
|
||||
"-pie -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169e" \
|
||||
"pass.out" \
|
||||
"-fPIE -O2 -g" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr23169f" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,now tmpdir/libpr23169b.so" \
|
||||
"" \
|
||||
{ pr23169b.c pr23169c.c } \
|
||||
"pr23169f" \
|
||||
"pass.out" \
|
||||
"-fPIE -O2 -g" \
|
||||
] \
|
||||
]
|
||||
|
9
ld/testsuite/ld-ifunc/pr23169a.c
Normal file
9
ld/testsuite/ld-ifunc/pr23169a.c
Normal file
@ -0,0 +1,9 @@
|
||||
int (*func_p) (void);
|
||||
extern int func (void);
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
if (func_p != &func || func_p () != 0xbadbeef)
|
||||
__builtin_abort ();
|
||||
}
|
6
ld/testsuite/ld-ifunc/pr23169a.rd
Normal file
6
ld/testsuite/ld-ifunc/pr23169a.rd
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
Symbol table '\.dynsym' contains [0-9]+ entries:
|
||||
+Num: +Value +Size Type +Bind +Vis +Ndx Name
|
||||
#...
|
||||
+[0-9]+: +[a-f0-9]+ +0 +FUNC +GLOBAL +DEFAULT +[0-9]+ +func
|
||||
#...
|
23
ld/testsuite/ld-ifunc/pr23169b.c
Normal file
23
ld/testsuite/ld-ifunc/pr23169b.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern int (*func_p) (void);
|
||||
extern int func (void);
|
||||
extern void foo (void);
|
||||
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
if (func_p != &func || func_p () != 0xbadbeef)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
func_p = &func;
|
||||
foo ();
|
||||
bar ();
|
||||
printf ("PASS\n");
|
||||
return 0;
|
||||
}
|
3
ld/testsuite/ld-ifunc/pr23169b.rd
Normal file
3
ld/testsuite/ld-ifunc/pr23169b.rd
Normal file
@ -0,0 +1,3 @@
|
||||
#failif
|
||||
[a-f0-9]+ +[0-9a-f]+ +R_.*_* +[a-f0-9]+ +func(| \+ 0)
|
||||
...
|
13
ld/testsuite/ld-ifunc/pr23169c.c
Normal file
13
ld/testsuite/ld-ifunc/pr23169c.c
Normal file
@ -0,0 +1,13 @@
|
||||
static int
|
||||
ifunc (void)
|
||||
{
|
||||
return 0xbadbeef;
|
||||
}
|
||||
|
||||
void func(void) __attribute__((ifunc("resolve_func")));
|
||||
|
||||
static void *
|
||||
resolve_func (void)
|
||||
{
|
||||
return ifunc;
|
||||
}
|
6
ld/testsuite/ld-ifunc/pr23169c.rd
Normal file
6
ld/testsuite/ld-ifunc/pr23169c.rd
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
Symbol table '\.dynsym' contains [0-9]+ entries:
|
||||
+Num: +Value +Size Type +Bind +Vis +Ndx Name
|
||||
#...
|
||||
+[0-9]+: +[a-f0-9]+ +[0-9]+ +IFUNC +GLOBAL +DEFAULT +[0-9]+ +func
|
||||
#...
|
Loading…
Reference in New Issue
Block a user