https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88262
--- Comment #18 from Andrew Pinski <pinskia at gcc dot gnu.org> --- So looking into the gcc's header files, we have the following in gnu-user.h: "%{shared:; \ pg|p|profile:gcrt1.o%s; \ static:crt1.o%s; \ " PIE_SPEC ":Scrt1.o%s; \ :crt1.o%s} \ So every linux target uses crt1.o for non-PIE based executables. The question I have is why is gold not doing the correct thing for those relocations; shouldn't behaving the similar ones for other function pointers loads? In fact for: int f(void); typedef int (*h)(void); h g(void) { return f; } We get: g: adrp x0, f add x0, x0, :lo12:f ret Which is exactly what is in start.S and in crt1.o. So my guess it is a bug in either how the runtime relocations are incorrectly being created with gold or being resolved incorrectly inside glibc's ld.so. Again what happens if you use BFD based ld? Does it work? If it does, then can you look into the difference in the runtime relocations that are being created? This is the only thing which would be causing the difference. Also note all targets have similar code like the above in crt1.o and they all work so there must be something wrong in either gold creation of runtime relocations or glibc's resolution of those runtime relocations (all for AARCH64).