]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: make ppc64le __glink_PLTresolve position-independent
authorPaul E. Murphy <murp@ibm.com>
Wed, 20 Oct 2021 18:40:54 +0000 (13:40 -0500)
committerLynn Boger <laboger@linux.vnet.ibm.com>
Mon, 1 Nov 2021 13:08:16 +0000 (13:08 +0000)
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>
src/cmd/link/internal/ppc64/asm.go

index 95070106035b557f4f5797915b0e99550ab60db6..62b319d19648d30a69410785dc3d00df58b6c991 100644 (file)
@@ -1067,35 +1067,31 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde
                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
        // for the target routine and the argument registers hold the
        // 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.
-       // Other things will be relative to this.
        glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0
        glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f
        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.
-       // Because this is PIC, everything is relative to label 1b (in
-       // r11):
-       //   r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
-       glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48
+       // Compute the .plt array index from the entry point address
+       // into r0. This is computed relative to label 1 above.
+       glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b)
        glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12
        glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11
        glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
 
-       // r11 = address of the first byte of the PLT
-       r, _ := glink.AddRel(objabi.R_ADDRPOWER)
-       r.SetSym(ctxt.PLT)
-       r.SetSiz(8)
-       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 the PC-rel offset of ".plt - 1b", and add it to 1b.
+       // This is stored after this stub and before the resolvers.
+       glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11)
+       glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12
 
        // Load r12 = dynamic resolver address and r11 = DSO
        // 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, 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.
        //   res_0: