riscv64: fix ifuncs, improve the ifunc tests.
Talking futher to the person doing the glibc risc-v ifunc work, they
clarified that glibc _is_ passing hwcap as the first argument, and the
null pointer is actually the second argument.
https://sourceware.org/pipermail/libc-alpha/2023-August/150967.html
So since our whole purpose here was source compatibility, let's do what
they're actually doing, and let's add some tests. I've also added a test
that __riscv_hwprobe() works from an ifunc resolver because that's one
place where it might well be used. That said, one other thing that came
out of the discussion is that I actually went away and looked at a
sample of top apps to see how many are using ifuncs currently. The
result? Zero. So although this _might_ be interesting long term
(especially if clang gets riscv64 FMV), I think we've done more than we
need to with riscv64 ifuncs for now!
Test: ran locally, both dynamic and static tests
Change-Id: Ie2044d9f4e47c32c00ad381f045c537f4df38b08
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index 410eb78..3cfb8b5 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -58,12 +58,12 @@
}
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap);
#elif defined(__riscv)
- // This argument and its value is just a placeholder for now,
- // but it means that if we do pass something in future (such as
- // getauxval() and/or hwprobe key/value pairs), callees will be able to
- // recognize what they're being given.
- typedef ElfW(Addr) (*ifunc_resolver_t)(void*);
- return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(nullptr);
+ // The pointer argument is currently unused, but reserved for future
+ // expansion. If we pass nullptr from the beginning, it'll be easier
+ // to recognize if/when we pass actual data (and matches glibc).
+ typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, void*);
+ static uint64_t hwcap = getauxval(AT_HWCAP);
+ return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, nullptr);
#else
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)();