Page MenuHomeFreeBSD

Handle non-plt IRELATIVE relocations.
ClosedPublic

Authored by kib on Feb 12 2020, 5:50 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Apr 12, 9:04 AM
Unknown Object (File)
Mar 15 2024, 9:48 AM
Unknown Object (File)
Feb 10 2024, 11:33 AM
Unknown Object (File)
Feb 10 2024, 11:33 AM
Unknown Object (File)
Feb 9 2024, 1:22 AM
Unknown Object (File)
Jan 14 2024, 9:06 PM
Unknown Object (File)
Jan 8 2024, 8:19 PM
Unknown Object (File)
Jan 8 2024, 8:10 PM

Details

Summary

amd64 only ATM, will add i386 if this works.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

Overall seems reasonable

libexec/rtld-elf/amd64/reloc.c
306

tiny nit, extra space here compared to others

kib marked an inline comment as done.Feb 12 2020, 10:10 PM

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)

actually I'm wrong.. I was confusing gnu ifuncs and non-plt gnu ifuncs, it was only the non-plt ones that got nerfed in rS341441 and rS343484.

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. :)

This revision is now accepted and ready to land.Feb 13 2020, 12:38 AM

Add other arches.
It might be that powerpc/powerpc64 already handle that.

Nothing tested.

This revision now requires review to proceed.Feb 13 2020, 11:12 AM

Also, is there a fresher description of any of this than the old ifunc.txt file from https://sites.google.com/site/x32abi/documents ?

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.

This variant passed tinderbox.

This revision was not accepted when it landed; it landed in state Needs Review.Feb 13 2020, 11:42 PM
This revision was automatically updated to reflect the committed changes.

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

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 D23652#708723, @kib wrote:

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?

In D23652#708723, @kib wrote:

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.