https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108315
Alan Modra <amodra at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amodra at gmail dot com --- Comment #5 from Alan Modra <amodra at gmail dot com> --- Any caller of bar should be fine. The localentry value of 1 means it is advertised as having no requirement on r2 or r12 and r2 is *not* preserved. A call that uses R_PPC64_REL24 to bar ought to have an r2 saving stub inserted by the linker and the nop after the call changed to restore r2. GNU ld will do exactly that. 0000000010000540 <00000047.long_branch.bar>: 10000540: 18 00 41 f8 std r2,24(r1) 10000544: 4c 02 00 48 b 10000790 <bar> ... 00000000100005a0 <main>: 100005a0: 02 10 40 3c lis r2,4098 100005a4: 00 7f 42 38 addi r2,r2,32512 100005a8: a6 02 08 7c mflr r0 100005ac: 00 00 00 60 nop 100005b0: 20 80 62 e8 ld r3,-32736(r2) 100005b4: 10 00 01 f8 std r0,16(r1) 100005b8: e1 ff 21 f8 stdu r1,-32(r1) 100005bc: 85 ff ff 4b bl 10000540 <00000047.long_branch.bar> 100005c0: 18 00 41 e8 ld r2,24(r1) There isn't a problem if bar is passed the address of a non-pcrel function in a shared library as it is in your example. The call in bar will go to the global entry point of foo, which will set up r2. The same thing happens when linking against foo.o, the function pointer address is that of the global entry of foo. [amodra@gcc135 p10-interop]$ ./smain Hello from foo Hello, World! (My dynamic main won't run on gcc135 due to my build machine having a more recent glibc, but I'm confident it would run if I fixed that.) I don't see any problem here other than (presumably) missing linker support.