[hjl@gnu-6 ifunc-xxx]$ cat foo.c static int two (void) { return 2; } void * foo_ifunc (void) __asm__ ("foo") __attribute__ ((visibility ("hidden"))); __asm__(".type foo, %gnu_indirect_function"); void * foo_ifunc (void) { return two; } extern int foo (void) __attribute__ ((visibility ("hidden"))); int (*foo1_ptr) (void); void bar (void) { foo1_ptr = foo; } [hjl@gnu-6 ifunc-xxx]$ cat main.c #include <stdlib.h> extern int (*foo1_ptr) (void); extern void bar (void); int main (void) { int foo1; bar (); foo1 = foo1_ptr (); if (foo1 != 2) abort (); return 0; } [hjl@gnu-6 ifunc-xxx]$ make gcc -m32 -O3 -c -o main.o main.c gcc -m32 -O3 -fPIC -c -o foo.o foo.c ./ld -m elf_i386 --shared -o libfoo.so -z nocombreloc foo.o gcc -m32 -o main main.o libfoo.so -Wl,-rpath,. ./main make: *** [all] Segmentation fault [hjl@gnu-6 ifunc-xxx]$
This may never work correctly for i386 since its PLT entry uses %ebx: 000001b0 <foo@plt>: 1b0: ff a3 0c 00 00 00 jmp *0xc(%ebx) 1b6: 68 00 00 00 00 push $0x0 1bb: e9 e0 ff ff ff jmp 1a0 <foo@plt-0x10> We can't return pointer to PLT entry since wrong %ebx may be used when calling it.
This is the known limitation in i386 IFUNC. The work around is not mark IFUNC function hidden.
Dup. *** This bug has been marked as a duplicate of bug 20515 ***
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=74437ea28fb611d4c88077b486fd7c0a8b4c2a25 commit 74437ea28fb611d4c88077b486fd7c0a8b4c2a25 Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon Aug 29 08:12:59 2016 -0700 i386: Issue an error on non-PIC call to IFUNC in PIC object On i386, IFUNC function must be called via PLT. Since PLT in PIC object uses EBX register, R_386_PLT32 relocation must be used to call IFUNC function even when IFUNC function is defined locally. Linker should issue an error when R_386_PC32 relocation is used to call IFUNC function. Since PR ld/19784 tests doesn't use PLT relocation to local IFUNC function, they are moved to the x86-64 test directory. bfd/ PR ld/14961 PR ld/20515 * elf32-i386.c (elf_i386_check_relocs): Issue an error when R_386_PC32 relocation is used to call IFUNC function in PIC object. ld/ PR ld/14961 PR ld/20515 * testsuite/ld-i386/i386.exp: Run pr20515. * testsuite/ld-i386/pr20515.d: New file. * testsuite/ld-i386/pr20515.s: Likewise. * testsuite/ld-ifunc/ifunc-14a.s: Use R_386_PLT32 to call IFUNC function. * testsuite/ld-ifunc/ifunc-14c.s: Likewise. * testsuite/ld-ifunc/ifunc-2-i386.s: Likewise. * testsuite/ld-ifunc/ifunc-2-local-i386.s: Likewise. * testsuite/ld-ifunc/ifunc.exp: Move PR ld/19784 tests to ... * testsuite/ld-x86-64/x86-64.exp: Here. * testsuite/ld-ifunc/pr19784a.c: Moved to ... * testsuite/ld-x86-64/pr19784a.c: Here. * testsuite/ld-ifunc/pr19784b.c: Moved to ... * testsuite/ld-x86-64/pr19784b.c: Here. * testsuite/ld-ifunc/pr19784c.c: Moved to ... * testsuite/ld-x86-64/pr19784c.c: Here.