aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2018-05-14 03:55:37 -0700
committerH.J. Lu <hjl.tools@gmail.com>2018-05-14 03:55:50 -0700
commit4ec0995016801cc5d5cf13baf6e10163861e6852 (patch)
treef2aa11725ad03aec8080cb88b6415c7fcdf2098f /bfd
parent9bc935ef3380a2d471b9447e2bf8e61297654e2f (diff)
downloadgdb-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/ChangeLog12
-rw-r--r--bfd/elf-ifunc.c9
-rw-r--r--bfd/elf32-i386.c2
-rw-r--r--bfd/elf64-x86-64.c2
-rw-r--r--bfd/elfxx-x86.c46
-rw-r--r--bfd/elfxx-x86.h4
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 \