1
0
mirror of https://github.com/golang/go synced 2024-11-24 07:50:13 -07:00

cmd/link: make ppc64le __glink_PLTresolve position-independent

This code is only generated when linking cgo internally with fixed
position code. This feature of the internal linker is only supported
on ppc64le/linux targets. This moves ppc64le/linux a little closer
to supporting PIE when internal linking.

This is more similar to the implementation suggested in the power
architecture elfv2 supplement, and works with both PIE and static
code.

Change-Id: I0b64e1c22b9e07b5151378d2ab19ee0e50405fc5
Reviewed-on: https://go-review.googlesource.com/c/go/+/357332
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Paul E. Murphy 2021-10-20 13:40:54 -05:00 committed by Lynn Boger
parent fde4cc2a31
commit 732db407d3

View File

@ -1067,35 +1067,31 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde
return glink return glink
} }
// This is essentially the resolver from the ppc64 ELF ABI. // This is essentially the resolver from the ppc64 ELFv2 ABI.
// At entry, r12 holds the address of the symbol resolver stub // At entry, r12 holds the address of the symbol resolver stub
// for the target routine and the argument registers hold the // for the target routine and the argument registers hold the
// arguments for the target routine. // arguments for the target routine.
// //
// PC-rel offsets are computed once the final codesize of the
// resolver is known.
//
// This stub is PIC, so first get the PC of label 1 into r11. // This stub is PIC, so first get the PC of label 1 into r11.
// Other things will be relative to this.
glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0 glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0
glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f
glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11
glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0 glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlr r0
// Compute the .plt array index from the entry point address. // Compute the .plt array index from the entry point address
// Because this is PIC, everything is relative to label 1b (in // into r0. This is computed relative to label 1 above.
// r11): glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b)
// r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48
glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12
glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11
glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
// r11 = address of the first byte of the PLT // Load the PC-rel offset of ".plt - 1b", and add it to 1b.
r, _ := glink.AddRel(objabi.R_ADDRPOWER) // This is stored after this stub and before the resolvers.
r.SetSym(ctxt.PLT) glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11)
r.SetSiz(8) glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12
r.SetOff(int32(glink.Size()))
r.SetAdd(0)
glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha
glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l
// Load r12 = dynamic resolver address and r11 = DSO // Load r12 = dynamic resolver address and r11 = DSO
// identifier from the first two doublewords of the PLT. // identifier from the first two doublewords of the PLT.
@ -1106,6 +1102,19 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde
glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr
// Store the PC-rel offset to the PLT
r, _ := glink.AddRel(objabi.R_PCREL)
r.SetSym(ctxt.PLT)
r.SetSiz(8)
r.SetOff(int32(glink.Size()))
r.SetAdd(glink.Size()) // Adjust the offset to be relative to label 1 above.
glink.AddUint64(ctxt.Arch, 0) // The offset to the PLT.
// Resolve PC-rel offsets above now the final size of the stub is known.
res0m1b := glink.Size() - 8 // res_0 - 1b
glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b)))
glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8)))
// The symbol resolvers must immediately follow. // The symbol resolvers must immediately follow.
// res_0: // res_0: