The linker code currently assumes that ifunc relocations are of type
R_[*]_IRELATIVE, but with -z ifunc-noplt this is no longer true.
In particular, we may also have to apply PC-relative relocations.
Such relocations require a symbol lookup. The default symbol lookup
function, elf_lookup(), calls a kern_linker.c function which performs
a kobj call, which can't work early during boot.
Address these problems:
- Add a custom symbol lookup function which simply invokes the ifunc resolver and otherwise returns ENOENT if the symbol is not of type GNU_IFUNC. Add a lookup callback to relocate_file1() so that we can use this custom lookup routine early during boot. I like this approach because it helps minimize the amount of kernel code that may be executed for ifunc resolution is performed.
- Apply all relocations in the kernel executable during boot, rather than trying to filter ifunc relocations. I believe we can safely do this on at least x86.
- Don't apply ifunc relocations in a separate pass when loading a .so kernel module. elf_reloc_internal() no longer has an easy way of determining whether a given relocation applies to an ifunc or not, and we cannot simply apply all relocations twice since they may not be idempotent.