amd64 only ATM, will add i386 if this works.
Details
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
Overall seems reasonable
libexec/rtld-elf/amd64/reloc.c | ||
---|---|---|
306 ↗ | (On Diff #68211) | tiny nit, extra space here compared to others |
fwiw I believe obj->gnu_ifunc is a vestigial bit of an earlier attempt to do non-plt ifuncs that got killed off in rS343484 and is the same as you are doing now (i.e. non-plt ifuncs)
Is there any case where IRELATIVE is used outside of GNU IFUNC btw?
Also, is there a fresher description of any of this than the old ifunc.txt file from https://sites.google.com/site/x32abi/documents ?
(A blatant error in that document is that it defines that the resolver takes no parameters. Given the resolver is called before the PLT is up and running, this is stupid, because on non x86* cpus, the cpu model information is coming from the auxv and is not directly available through an unprivileged instruction, so the workaround on x86* of __builtin_cpu_supports() calls is nonsensical. FreeBSD ifuncs always pass the available cpu feature flags in as parameters to the resolver, even on x86* where you can theoretically get it from a compiler builtin)
This appears to work OK for libc.so.7 linked with lld 10.0.0, e.g. with IRELATIVE relocations in the .rela.dyn section. I copied the resulting ld-elf.so.1 to /libexec, and the newly linked libc.so.7 to /lib, and I haven't found anything yet which doesn't run. :)
Add other arches.
It might be that powerpc/powerpc64 already handle that.
Nothing tested.
I am not sure, the descriptions of IRELATIVE and GNU_IFUNC are embedded into psABI docs for x86 now.
I seem to get compilation errors with the latest version of this:
/usr/src/libexec/rtld-elf/i386/reloc.c:266:8: error: use of undeclared identifier 'R_I386_IRELATIVE' case R_I386_IRELATIVE: ^ /usr/src/libexec/rtld-elf/i386/reloc.c:396:28: error: incompatible pointer types passing 'const Elf_Rel *' (aka 'const Elf32_Rel *') to parameter of type 'const Elf_Rela *' (aka 'const Elf32_Rela *') [-Werror ,-Wincompatible-pointer-types] --- all_subdir_bin --- --- all_subdir_bin/pwd --- ===> bin/pwd (all) --- all_subdir_libexec --- reloc_iresolve_one(obj, rel, lockstate); ^~~ /usr/src/libexec/rtld-elf/i386/reloc.c:372:52: note: passing argument to parameter 'rel' here reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rel, ^ /usr/src/libexec/rtld-elf/i386/reloc.c:412:34: error: use of undeclared identifier 'R_I386_IRELATIVE' if (ELF_R_TYPE(rel->r_info) == R_I386_IRELATIVE) ^ /usr/src/libexec/rtld-elf/i386/reloc.c:413:28: error: incompatible pointer types passing 'const Elf_Rel *' (aka 'const Elf32_Rel *') to parameter of type 'const Elf_Rela *' (aka 'const Elf32_Rela *') [-Werror ,-Wincompatible-pointer-types] reloc_iresolve_one(obj, rel, lockstate); ^~~ /usr/src/libexec/rtld-elf/i386/reloc.c:372:52: note: passing argument to parameter 'rel' here reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rel, ^ 4 errors generated. *** [reloc.o] Error code 1
It looks like s/R_I386_IRELATIVE/R_386_IRELATIVE/g should help. Not sure why the naming of the macro is inconsistent, probably a historic thing.
Where do you think R_*_IRELATIVE should reside in? .rela.dyn or .rela.plt?
GNU ld's x86 port picks .rela.plt for https://sourceware.org/bugzilla/show_bug.cgi?id=13302
which may be related to this sentence "This may work on x86_64 where the R_*_IRELATIVE relocations happen in DT_JMPREL after the DT_REL* relocations, but that is no guarantee that it will work on AArch64, PPC64, or other architectures that are slightly different" on https://sourceware.org/glibc/wiki/GNU_IFUNC
For us it should not make a difference. We process whole DT_RELA while looking for IRELATIVE.
In glibc lazy binding mode, if an IRELATIVE is before a JUMP_SLOT, and the ifunc resolver calls a function associated to the JUMP_SLOT, the ifunc resolver may crash because the JUMP_SLOT is not set yet.
Can I assume that you mean this case works perfectly fine with FreeBSD rtld?
FreeBSD rtld does the initial pass over the plt relocations and handles R_X86_64_JMP_SLOT only, If there are any R_X86_64_IRELATIVE relocks, we mark the object as having such relocations. Then, we do the ireloc processing, using the depth-first descend. We handle all IRELOCs for dependent objects before doing it for dependee. There, we iterate over all plt relocs to select IRELOCs.