https://sourceware.org/bugzilla/show_bug.cgi?id=28218
Bug ID: 28218 Summary: ld: ifunc resolver calls a lazy PLT. When does it work? Product: binutils Version: unspecified Status: UNCONFIRMED Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: i at maskray dot me Target Milestone: --- If an ifunc resolver calls a PLT with lazy JUMP_SLOT, should it work? My impression is that this does not necessarily need to work. That said, the R_X86_64_IRELATIVE in .rela.plt is special. PR ld/13302 patched GNU ld to place R_X86_64_IRELATIVE in .rela.plt after JUMP_SLOT. This allows lazy PLT calls. I think if this case is to be supported, ld.so is to be patched instead. IRELATIVE relocations are eagerly resolved. .rela.dyn is conceptually a better place, similar to the .plt.got GLOB_DAT optimization. IRELATIVE relocations are not PLT. FreeBSD rtld resolves non-IRELATIVE relocations in all modules, then IRELATIVE relocations in all modules. This allows flexibility on what can be used in ifunc resolvers, and linkers don't need to place IRELATIVE in special places. cat > a.c <<eof #include <stdio.h> int a_impl() { return 42; } void *a_resolver() { puts("a_resolver"); return (void *)a_impl; } int a() __attribute__((ifunc("a_resolver"))); // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn int (*fptr_a)() = a; int main() { printf("%d\n", a()); } eof cc -fpie -c a.c cc -fuse-ld=bfd -pie a.o -o a % ./a [1] 170657 segmentation fault ./a % readelf -Wr a Relocation section '.rela.dyn' at offset 0x4b0 contains 9 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000003de8 0000000000000008 R_X86_64_RELATIVE 1150 0000000000003df0 0000000000000008 R_X86_64_RELATIVE 1110 0000000000004038 0000000000000008 R_X86_64_RELATIVE 4038 0000000000003fd8 0000000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMCloneTable + 0 0000000000003fe0 0000000400000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 0000000000003fe8 0000000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 0000000000003ff0 0000000600000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTable + 0 0000000000003ff8 0000000700000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 0000000000004040 0000000000000025 R_X86_64_IRELATIVE 1160 Relocation section '.rela.plt' at offset 0x588 contains 3 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000004018 0000000200000007 R_X86_64_JUMP_SLOT 0000000000000000 puts@GLIBC_2.2.5 + 0 0000000000004020 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000000 printf@GLIBC_2.2.5 + 0 0000000000004028 0000000000000025 R_X86_64_IRELATIVE 1160 `int (*fptr_a)() = a;` leads to an R_X86_64_IRELATIVE in .rela.dyn . If lazy binding is used, when the R_X86_64_IRELATIVE is resolved, R_X86_64_JUMP_SLOT(puts) hasn't been resolved yet, and the program crashes. R_X86_64_IRELATIVE can be seen as an optimization. R_X86_64_64 referencing an STT_GNU_IFUNC symbol is a different representation. --- cat > b.c <<eof #include <stdio.h> int b_impl() { return 42; } void *b_resolver() { puts("b resolver"); return (void *)b_impl; } int b() __attribute__((ifunc("b_resolver"))); int (*fptr_b)() = b; eof cc b.c -fpic -shared -o b.so Make b.so a DT_NEEDED of the executable and see the crash again. In this case, R_X86_64_64 is used instead of IRELATIVE. (b is preemptible, so IRELATIVE cannot be used.) https://sourceware.org/pipermail/libc-alpha/2021-August/129968.html says "I don't believe this is the use case we want to support." -- You are receiving this mail because: You are on the CC list for the bug.