+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
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)
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
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
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
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 \
+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
--- /dev/null
+#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[ ]*
--- /dev/null
+#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]*
+++ /dev/null
-#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-*-*
{} \
"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 \
"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" \
+ ] \
]
--- /dev/null
+int (*func_p) (void);
+extern int func (void);
+
+void
+foo (void)
+{
+ if (func_p != &func || func_p () != 0xbadbeef)
+ __builtin_abort ();
+}
--- /dev/null
+
+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
+#...
--- /dev/null
+#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;
+}
--- /dev/null
+#failif
+[a-f0-9]+ +[0-9a-f]+ +R_.*_* +[a-f0-9]+ +func(| \+ 0)
+...
--- /dev/null
+static int
+ifunc (void)
+{
+ return 0xbadbeef;
+}
+
+void func(void) __attribute__((ifunc("resolve_func")));
+
+static void *
+resolve_func (void)
+{
+ return ifunc;
+}
--- /dev/null
+
+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
+#...