The PR ld/13302 changes broke not only x86_64 (fixed http://sources.redhat.com/ml/binutils-cvs/2012-03/msg00019.html ), but also i386. ifunc3.sh test in prelink fails because of that. The problem is that you just can't on i?86 use a standard PLT entry for what you want to do, because unlike x86_64 in i?86 shared libraries/PIEs the PLT slot assumes that %ebx of the caller points to the _GLOBAL_OFFSET_TABLE_ symbol of the library containing the PLT slot. That is normally the responsibility of the compiler or assembly writer, but in this case where you just have a function pointer that resolves internally to an IFUNC symbol you have no such guarantee. If that function pointer is called from the main binary, %ebx can contain random garbage, if it is called from some other shared library, it will contain address of a different _GLOBAL_OFFSET_TABLE_ symbol.
Created attachment 6264 [details] ifunctest.tar.bz2 CC='gcc -m32' sh ./ifunc.sh LD_LIBRARY_PATH=. ./ifunc3 shows the segfault (the PLT calling completely unrelated function).
So we have to use real function, not PLT entry for non-GOT reference to locally defined IFUNC symbols, at least on i386. Will revert: http://sourceware.org/ml/binutils/2011-10/msg00203.html cause any problems? It will put IRELATIVE relocations in .rel.dyn/.rela.dyn section, which was the previous behavior.
I think you can keep x86_64 as is. For i386 such PLT slots in the non-pic binaries could stay, but if we don't have any registers that we can clobber, the special alternate plt slots that would be needed would be complicated, especially when there is no red zone on i386. So perhaps reverting that patch for i386 or limiting it to non-PIE executables is the best short time fix, until we figure out something that will work. Without spare registers/red zone the only alternatives I can imagine are either one breaking the call/ret heuristics in the CPU (i.e. compute the desired address in the return slot on the stack (after call) and then ret to it), or using some __thread variable to hold where would we jump to.
I'd like to keep i386 consistent with x86-64 as much as possible. I will revert both changes.
CVSROOT: /cvs/src Module name: src Changes by: hjl@sourceware.org 2012-03-09 16:28:38 Modified files: bfd : ChangeLog elf32-i386.c elf64-x86-64.c ld/testsuite : ChangeLog ld/testsuite/ld-i386: pr13302.d ld/testsuite/ld-x86-64: pr13082-5b.d pr13082-6a.d pr13082-6b.d Log message: Restore R_386_IRELATIVE and R_X86_64_IRELATIVE bfd/ 2012-03-09 H.J. Lu <hongjiu.lu@intel.com> PR ld/13817 * bfd/elf32-i386.c (elf_i386_relocate_section): Restore R_386_IRELATIVE. * * elf64-x86-64.c (elf_x86_64_relocate_section): Restore R_X86_64_IRELATIVE. ld/testsuite/ 2012-03-09 H.J. Lu <hongjiu.lu@intel.com> PR ld/13817 * ld-i386/pr13302.d: Updated. * ld-x86-64/pr13082-5b.d: Likewise. * ld-x86-64/pr13082-6a.d: Likewise. * ld-x86-64/pr13082-6b.d: Likewise. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5624&r2=1.5625 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf32-i386.c.diff?cvsroot=src&r1=1.265&r2=1.266 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf64-x86-64.c.diff?cvsroot=src&r1=1.248&r2=1.249 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1499&r2=1.1500 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-i386/pr13302.d.diff?cvsroot=src&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/pr13082-5b.d.diff?cvsroot=src&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/pr13082-6a.d.diff?cvsroot=src&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/pr13082-6b.d.diff?cvsroot=src&r1=1.2&r2=1.3
Fixed.