[hjl@gnu-cfl-1 ifunc-exec]$ cat main.c 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 (); return 0; } [hjl@gnu-cfl-1 ifunc-exec]$ cat func.c static int ifunc (void) { return 0xbadbeef; } void func(void) __attribute__((ifunc("resolve_func"))); static void * resolve_func (void) { return ifunc; } [hjl@gnu-cfl-1 ifunc-exec]$ cat foo.c int (*func_p) (void); extern int func (void); void foo (void) { if (func_p != &func || func_p () != 0xbadbeef) __builtin_abort (); } [hjl@gnu-cfl-1 ifunc-exec]$ make gcc -g -c -o main.o main.c gcc -g -c -o func.o func.c gcc -g -fPIC -c -o foo.o foo.c gcc -shared -o libfoo.so foo.o gcc -o x main.o func.o libfoo.so -Wl,-R,. /usr/local/bin/ld: dynamic STT_GNU_IFUNC symbol `func' with pointer equality in `func.o' can not be used when making an executable; recompile with -fPIE and relink with -pie collect2: error: ld returned 1 exit status make: *** [Makefile:17: x] Error 1 [hjl@gnu-cfl-1 ifunc-exec]$ If STT_GNU_IFUNC symbol is defined in 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.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4ec0995016801cc5d5cf13baf6e10163861e6852 commit 4ec0995016801cc5d5cf13baf6e10163861e6852 Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon May 14 03:55:37 2018 -0700 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.
Fixed for 2.31.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2822b09ff6024d042f1258194d6938c5a401b4fb commit 2822b09ff6024d042f1258194d6938c5a401b4fb Author: Alan Modra <amodra@gmail.com> Date: Tue Jun 26 14:30:16 2018 +0930 PR23169 bogus test The testcase isn't valid. If it happens to run on your target, you're lucky. PR 23169 * testsuite/ld-ifunc/ifunc.exp: Don't run pr23169 tests on powerpc. Comment.
The binutils-2_31-branch branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=83195288b7af4d5f2edfed35a20cbf4d59cb4996 commit 83195288b7af4d5f2edfed35a20cbf4d59cb4996 Author: Alan Modra <amodra@gmail.com> Date: Tue Jun 26 14:30:16 2018 +0930 PR23169 bogus test The testcase isn't valid. If it happens to run on your target, you're lucky. PR 23169 * testsuite/ld-ifunc/ifunc.exp: Don't run pr23169 tests on powerpc. Comment.
The master branch has been updated by Andre Simoes Dias Vieira <avieira@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3ba174474d3cc063d6b7abf0bfdd6021bbaf8a90 commit 3ba174474d3cc063d6b7abf0bfdd6021bbaf8a90 Author: Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> Date: Thu Jul 19 16:18:28 2018 +0100 [PATCH, LD, AArch64] Fix ifunc testisms This patch fixes some ifunc testisms after H.J. Lu's patch to enable the use of IFUNC pointers in position dependent code for binutils. See PR LD/23169 in binutils bugzilla. The aarch64 ifunc error message test was changed to no longer expect this error message as this is now an accepted combination. This patch also disables the executable tests added by H.J. Lu for aarch64, just as Alan Modra did with his patch, as these tests only seem to work on some architectures. ld/ChangeLog: 2018-07-19 Andre Vieira <andre.simoesdiasvieira@arm.com> * testsuite/ld-aarch64/ifunc-9.d: Remove no longer expected error. * testsuite/ld-ifunc/ifunc.exp: Disable tests for aarch64.
The binutils-2_31-branch branch has been updated by Roland McGrath <roland@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=feaed904944b4c07c1335b81f0fc27b5988e33c8 commit feaed904944b4c07c1335b81f0fc27b5988e33c8 Author: Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> Date: Thu Jul 19 16:18:28 2018 +0100 [PATCH, LD, AArch64] Fix ifunc testisms This patch fixes some ifunc testisms after H.J. Lu's patch to enable the use of IFUNC pointers in position dependent code for binutils. See PR LD/23169 in binutils bugzilla. The aarch64 ifunc error message test was changed to no longer expect this error message as this is now an accepted combination. This patch also disables the executable tests added by H.J. Lu for aarch64, just as Alan Modra did with his patch, as these tests only seem to work on some architectures. ld/ChangeLog: 2018-07-19 Andre Vieira <andre.simoesdiasvieira@arm.com> * testsuite/ld-aarch64/ifunc-9.d: Remove no longer expected error. * testsuite/ld-ifunc/ifunc.exp: Disable tests for aarch64. (cherry picked from commit 3ba174474d3cc063d6b7abf0bfdd6021bbaf8a90)
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=75a933f39918ce4f4b9481234992895e022787ee commit 75a933f39918ce4f4b9481234992895e022787ee Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Jan 16 07:00:09 2021 -0800 ld/elf/x86: Don't compare IFUNC address in the shared object On x86, glibc 2.33 starts to issue a fatal error message when calling IFUNC function defined in the unrelocated executable from a shared library. 1. Update x86 ELF linker to always convert IFUNC function defined in position-dependent executable (PDE) to the normal function. GOT in PDE will be updated by R_*_IRELATIVE at run-time. 2. Update PR ld/23169 tests not to compare function address of external IFUNC function in the shared object to avoid calling the IFUNC function defined in the unrelocated executable. 3. Remove pr23169e tests which call the IFUNC function defined in the unrelocated position-independent executable from a shared library. bfd/ PR ld/23169 * elfxx-x86.c (_bfd_x86_elf_link_fixup_ifunc_symbol): Don't check pointer_equality_needed. ld/ PR ld/23169 * testsuite/ld-ifunc/ifunc.exp: Replace pr23169c.rd with pr23169a.rd for pr23169c and pr23169f. Remove pr23169e tests. * testsuite/ld-ifunc/pr23169a.c (foo): Don't compare function address.
Can https://sourceware.org/glibc/wiki/GNU_IFUNC to updated to document what is supported and what isn't supported? For the https://sourceware.org/bugzilla/show_bug.cgi?id=23169#c0 example, if you run: gcc -fpie -g -c -o main.o main.c gcc -fpie -g -c -o func.o func.c gcc -g -fPIC -c -o foo.o foo.c gcc -shared -o libfoo.so foo.o gcc -pie -o x main.o func.o libfoo.so -Wl,-R,. Previously, a STT_GNU_IFUNC did not need to be converted to STT_FUNC if there were only GOT-generating or PLT-generating relocations. func.o had only a GOT-generating relocation: R_X86_64_REX_GOTPCRELX. func was STT_GNU_IFUNC. After the recent GNU ld commit https://sourceware.org/bugzilla/show_bug.cgi?id=23169#c7 STT_GNU_IFUNC is converted to STT_FUNC regardless of the relocation type. func is STT_FUNC. Is the idea that (1) the main executable is relocated the last. (2) by making the main executable STT_GNU_IFUNC STT_FUNC, ifunc resolver will not be called while the main executable is unresolved (3) How does an ifunc resolver defined in another DSO work? Let the user ensures DT_NEEDED BFS order or the ld.so itself does topological sorting?
(In reply to Fangrui Song from comment #8) > Can https://sourceware.org/glibc/wiki/GNU_IFUNC to updated to document what > is supported and what isn't supported? > IFUNC documentation needs improvements. > > Is the idea that > (1) the main executable is relocated the last. > (2) by making the main executable STT_GNU_IFUNC STT_FUNC, ifunc resolver > will not be called while the main executable is unresolved Correct. > (3) How does an ifunc resolver defined in another DSO work? Let the user > ensures DT_NEEDED BFS order or the ld.so itself does topological sorting? Current ld.so issues an error with a suggestion when it detects it.
The binutils-2_36-branch branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e9815c344ef0d24405cfaf9968135ad2180649f8 commit e9815c344ef0d24405cfaf9968135ad2180649f8 Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Jan 16 07:00:09 2021 -0800 ld/elf/x86: Don't compare IFUNC address in the shared object On x86, glibc 2.33 starts to issue a fatal error message when calling IFUNC function defined in the unrelocated executable from a shared library. 1. Update x86 ELF linker to always convert IFUNC function defined in position-dependent executable (PDE) to the normal function. GOT in PDE will be updated by R_*_IRELATIVE at run-time. 2. Update PR ld/23169 tests not to compare function address of external IFUNC function in the shared object to avoid calling the IFUNC function defined in the unrelocated executable. 3. Remove pr23169e tests which call the IFUNC function defined in the unrelocated position-independent executable from a shared library. bfd/ PR ld/23169 * elfxx-x86.c (_bfd_x86_elf_link_fixup_ifunc_symbol): Don't check pointer_equality_needed. ld/ PR ld/23169 * testsuite/ld-ifunc/ifunc.exp: Replace pr23169c.rd with pr23169a.rd for pr23169c and pr23169f. Remove pr23169e tests. * testsuite/ld-ifunc/pr23169a.c (foo): Don't compare function address. (cherry picked from commit 75a933f39918ce4f4b9481234992895e022787ee)
(In reply to H.J. Lu from comment #9) > (In reply to Fangrui Song from comment #8) > > Can https://sourceware.org/glibc/wiki/GNU_IFUNC to updated to document what > > is supported and what isn't supported? > > > > IFUNC documentation needs improvements. > > > > > Is the idea that > > (1) the main executable is relocated the last. > > (2) by making the main executable STT_GNU_IFUNC STT_FUNC, ifunc resolver > > will not be called while the main executable is unresolved > > Correct. > > > (3) How does an ifunc resolver defined in another DSO work? Let the user > > ensures DT_NEEDED BFS order or the ld.so itself does topological sorting? > > Current ld.so issues an error with a suggestion when it detects it. I currently cannot find a straightforward rule to explain the GNU ld behavior and what is supported in glibc. cat > ./a.s <<eof resolver: ret .globl ifunc, _start .type ifunc, @gnu_indirect_function .set ifunc, resolver _start: movq ifunc@GOTPCREL(%rip), %rax call ifunc eof echo 'call ifunc' > ./b.s gcc -shared -fpic b.s -o b.so ~/Dev/binutils-gdb/Debug/ld/ld-new is a top-of-tree ld. % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic a.o -o a && readelf -W -s a | grep ifunc 7: 0000000000401008 0 IFUNC GLOBAL DEFAULT 3 ifunc % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic a.o ./b.so -o a && readelf -W -s a | grep ifunc 5: 0000000000401010 0 FUNC GLOBAL DEFAULT 7 ifunc 8: 0000000000401010 0 FUNC GLOBAL DEFAULT 7 ifunc % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic -pie a.o -o a && readelf -W --dyn-syms a | grep ifunc 5: 0000000000001020 0 IFUNC GLOBAL DEFAULT 8 ifunc % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic -pie a.o ./b.so -o a && readelf -W --dyn-syms a | grep ifunc 5: 0000000000001020 0 IFUNC GLOBAL DEFAULT 8 ifunc Is this a -no-pie only behavior?
(In reply to Fangrui Song from comment #11) > (In reply to H.J. Lu from comment #9) > > cat > ./a.s <<eof > resolver: > ret > > .globl ifunc, _start > .type ifunc, @gnu_indirect_function > .set ifunc, resolver > > _start: > movq ifunc@GOTPCREL(%rip), %rax > call ifunc > eof > echo 'call ifunc' > ./b.s > gcc -shared -fpic b.s -o b.so > > ~/Dev/binutils-gdb/Debug/ld/ld-new is a top-of-tree ld. > > % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic a.o -o a && readelf -W > -s a | grep ifunc > 7: 0000000000401008 0 IFUNC GLOBAL DEFAULT 3 ifunc Symbol type in .symtab isn't relevant to ld.so. > % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic a.o ./b.so -o a && > readelf -W -s a | grep ifunc > 5: 0000000000401010 0 FUNC GLOBAL DEFAULT 7 ifunc > 8: 0000000000401010 0 FUNC GLOBAL DEFAULT 7 ifunc > > % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic -pie a.o -o a && > readelf -W --dyn-syms a | grep ifunc > 5: 0000000000001020 0 IFUNC GLOBAL DEFAULT 8 ifunc > % ~/Dev/binutils-gdb/Debug/ld/ld-new --export-dynamic -pie a.o ./b.so -o a > && readelf -W --dyn-syms a | grep ifunc > 5: 0000000000001020 0 IFUNC GLOBAL DEFAULT 8 ifunc > > > Is this a -no-pie only behavior? Yes. We can do that only because position-dependent executable doesn't need to be relocated.
X86 linker uses a trick to use the PLT entry of IFUNC function in position-dependent executable as the function address for ALL internal and external references. We can do that because the PLT entry doesn't need ANY dynamic relocation.