pcc wrote: > How does this work in the non-PIE (PDE) case when we take the address of an > ifunc and pass it to a function in a shared library, which then compares the > argument with its own global address take of the ifunc? > > For example: shared lib > > ``` > typedef void Fptr(void); > extern void ifn(void); > > // take address of ifunc ifn defined in application > Fptr* ifp = &ifn; > > // compare address of ifn we have calculated in ifp vs > // address calculated by application, passed in fp1. > int compare(Fptr* fp1) { > return fp1 == ifp; > } > ``` > > App > > ``` > typedef void Fptr(void); > extern int compare(Fptr* fp1); > int val = 0; > static void impl(void) { val = 42; } > static void *resolver(void) { return impl; } > __attribute__((ifunc("resolver"))) void *ifn(); > > extern Fptr* fp; > > int main(void) { > return compare(fp); > } > // separate file so compiler is unaware ifn is an ifunc. > typedef void Fptr(void); > extern void ifn(void); > Fptr* fp = &ifn; > ``` > > Right now in the application lld produces an iPLT entry for `ifn`, with `fp` > pointing to the iPLT entry. The dynamic symbol table contains the address of > the iPLT entry with type STT_FUNC . The shared library and the argument > compare equal. > > As I understand it, this patch will change `fp` to point directly to the > result of the ifunc resolver. So unless we also change the value put into the > dynamic symbol table we'll stop comparing equal. > > I don't think there's a STT_FUNC symbol we can put in the dynamic symbol > table that holds the result of the ifunc resolver. GNU ld, puts the address > of the resolver function with a STT_GNU_IFUNC symbol type in the dynamic > symbol table. If that causes the dynamic loader to call the resolver and > replace the value with the result then that would work. I haven't had time to > check what glibc does though.
If a dynamic loader sees a symbol with type `STT_GNU_IFUNC` it will indeed call the resolver and use the return value when resolving relocations involving that symbol. You can see this behavior in glibc e.g. `elf_machine_rela` function in `sysdeps/aarch64/dl-machine.h` and bionic in the `resolve_symbol_address` function in `bionic/linker/linker_soinfo.h`. So in your example we will end up with `resolver` being called twice: once for the `R_AARCH64_ABS64` in the `ifp` initializer and once for the `R_AARCH64_IRELATIVE` in the `fp` initializer. So the comparison should still succeed. https://github.com/llvm/llvm-project/pull/133531 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits