diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-05-14 03:55:37 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-05-14 03:55:50 -0700 |
commit | 4ec0995016801cc5d5cf13baf6e10163861e6852 (patch) | |
tree | f2aa11725ad03aec8080cb88b6415c7fcdf2098f /bfd | |
parent | 9bc935ef3380a2d471b9447e2bf8e61297654e2f (diff) | |
download | gdb-4ec0995016801cc5d5cf13baf6e10163861e6852.zip gdb-4ec0995016801cc5d5cf13baf6e10163861e6852.tar.gz gdb-4ec0995016801cc5d5cf13baf6e10163861e6852.tar.bz2 |
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.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elf-ifunc.c | 9 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 2 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 2 | ||||
-rw-r--r-- | bfd/elfxx-x86.c | 46 | ||||
-rw-r--r-- | bfd/elfxx-x86.h | 4 |
6 files changed, 74 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 10b9679..f8138a1 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,17 @@ 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 * elfxx-x86.c (elf_x86_linker_defined): New function. (_bfd_x86_elf_link_check_relocs): Use it to mark __bss_start, diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index 5716ab3..b8a3632 100644 --- a/bfd/elf-ifunc.c +++ b/bfd/elf-ifunc.c @@ -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) diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index c1c4ed0..580a591 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -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 diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a0ebd2c..e5a4dbc 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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 diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 6c1f4c3..936b4c6 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -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 diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index efa835e..8f67c23 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -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 \ |