ppc64 ld : linker synthesized _savegpr* and _restgpr*

Fangrui Song maskray@google.com
Tue May 5 22:41:04 GMT 2020
Both ELFv1 (3.5.9. Save and Restore Services) and ELFv2 (2.3.3.1. GPR
Save and Restore Functions) mention _savegpr* and _restgpr*.

It surprised me a lot that ppc64 ld defines _savegpr* and _restgpr* if
these symbols are undefined or defined by linked shared objects.

   cat > a.s <<e
     bl _savegpr0_20
     nop
   e
   cat > b.s <<e
     .globl _savegpr0_20
     _savegpr0_20:
       blr
   e
   powerpc64le-linux-gnu-as a.s -o a.o
   powerpc64le-linux-gnu-as b.s -o b.o
   powerpc64le-linux-gnu-ld -shared b.o -o b.so
   powerpc64le-linux-gnu-ld a.o b.so -o bfd.exe        # defined as STB_LOCAL
   powerpc64le-linux-gnu-ld.gold a.o b.so -o gold.exe  # PLT


This is very unusual. I have only seen synthesized code in PLT and range
extension thunks (which havs other names like veneer and stub groups).
This discord deeply hurts me: functions are synthesized out of thin air.

The 2008 libgcc commit introducing these files left a simple comment:
https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/rs6000/crtsavgpr.asm;h=0e244316fa6ca6714a87d47b6a3729bc27824d92;hb=18724e30aca828678b4f0a788e26b90dc8c44c36#l45
with no reasoning.

Isn't it cleaner and more elegant to define these functions in libgcc, like
everything else does?

I acknowledge that the linker hack has one merit:
if, say, _savegpr0_20 is referenced, 14~19 will not be defined.

However, with binutils 2.35 unique and .reloc, we can easily achieve the same effect as long as ld --gc-sections is specified:

   awk 'BEGIN{
     for(i=14;i<=31;i++){
       s = i==31 ? "" : ".reloc 0,R_PPC64_NONE,_savegpr0_" (i+1) "; "
       print ".section .text,\"ax\",@progbits,unique," i "; .globl _savegpr0_" i "; _savegpr0_" i ": " s "std " i "," (i*8-256) "(1)"}
     print "std 0,16(1)\nblr" }' /dev/null > savegpr0.s

   .section .text,"ax",@progbits,unique,14; .globl _savegpr0_14; _savegpr0_14: .reloc 0,R_PPC64_NONE,_savegpr0_15; std 14,-144(1)
   .section .text,"ax",@progbits,unique,15; .globl _savegpr0_15; _savegpr0_15: .reloc 0,R_PPC64_NONE,_savegpr0_16; std 15,-136(1)
   .section .text,"ax",@progbits,unique,16; .globl _savegpr0_16; _savegpr0_16: .reloc 0,R_PPC64_NONE,_savegpr0_17; std 16,-128(1)
   .section .text,"ax",@progbits,unique,17; .globl _savegpr0_17; _savegpr0_17: .reloc 0,R_PPC64_NONE,_savegpr0_18; std 17,-120(1)
   .section .text,"ax",@progbits,unique,18; .globl _savegpr0_18; _savegpr0_18: .reloc 0,R_PPC64_NONE,_savegpr0_19; std 18,-112(1)
   .section .text,"ax",@progbits,unique,19; .globl _savegpr0_19; _savegpr0_19: .reloc 0,R_PPC64_NONE,_savegpr0_20; std 19,-104(1)
   .section .text,"ax",@progbits,unique,20; .globl _savegpr0_20; _savegpr0_20: .reloc 0,R_PPC64_NONE,_savegpr0_21; std 20,-96(1)
   .section .text,"ax",@progbits,unique,21; .globl _savegpr0_21; _savegpr0_21: .reloc 0,R_PPC64_NONE,_savegpr0_22; std 21,-88(1)
   .section .text,"ax",@progbits,unique,22; .globl _savegpr0_22; _savegpr0_22: .reloc 0,R_PPC64_NONE,_savegpr0_23; std 22,-80(1)
   .section .text,"ax",@progbits,unique,23; .globl _savegpr0_23; _savegpr0_23: .reloc 0,R_PPC64_NONE,_savegpr0_24; std 23,-72(1)
   .section .text,"ax",@progbits,unique,24; .globl _savegpr0_24; _savegpr0_24: .reloc 0,R_PPC64_NONE,_savegpr0_25; std 24,-64(1)
   .section .text,"ax",@progbits,unique,25; .globl _savegpr0_25; _savegpr0_25: .reloc 0,R_PPC64_NONE,_savegpr0_26; std 25,-56(1)
   .section .text,"ax",@progbits,unique,26; .globl _savegpr0_26; _savegpr0_26: .reloc 0,R_PPC64_NONE,_savegpr0_27; std 26,-48(1)
   .section .text,"ax",@progbits,unique,27; .globl _savegpr0_27; _savegpr0_27: .reloc 0,R_PPC64_NONE,_savegpr0_28; std 27,-40(1)
   .section .text,"ax",@progbits,unique,28; .globl _savegpr0_28; _savegpr0_28: .reloc 0,R_PPC64_NONE,_savegpr0_29; std 28,-32(1)
   .section .text,"ax",@progbits,unique,29; .globl _savegpr0_29; _savegpr0_29: .reloc 0,R_PPC64_NONE,_savegpr0_30; std 29,-24(1)
   .section .text,"ax",@progbits,unique,30; .globl _savegpr0_30; _savegpr0_30: .reloc 0,R_PPC64_NONE,_savegpr0_31; std 30,-16(1)
   .section .text,"ax",@progbits,unique,31; .globl _savegpr0_31; _savegpr0_31: std 31,-8(1)
   std 0,16(1)
   blr


More information about the Binutils mailing list