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

Reply via email to