]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/ppc64: avoid calling morestack via a PLT when dynamically linking
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Fri, 16 Oct 2015 07:50:59 +0000 (20:50 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Fri, 13 Nov 2015 00:36:22 +0000 (00:36 +0000)
Change-Id: Ie79f72786b1d7154f1910e717a0faf354b913b89
Reviewed-on: https://go-review.googlesource.com/15970
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/internal/obj/ppc64/obj9.go

index a876b99a76990c7e1fd577a1cb5553e48531dc42..696f6e5834cadfa21a8a883f4e9659539a8cc83a 100644 (file)
@@ -940,19 +940,62 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
                q.Pcond = p
        }
 
-       // BL   runtime.morestack(SB)
-       p = obj.Appendp(ctxt, p)
-
-       p.As = ABL
-       p.To.Type = obj.TYPE_BRANCH
+       var morestacksym *obj.LSym
        if ctxt.Cursym.Cfunc != 0 {
-               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+               morestacksym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
        } else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
-               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+               morestacksym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
        } else {
-               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
+               morestacksym = obj.Linklookup(ctxt, "runtime.morestack", 0)
        }
 
+       if ctxt.Flag_dynlink {
+               // Avoid calling morestack via a PLT when dynamically linking.  The
+               // PLT stubs generated by the system linker on ppc64le when "std r2,
+               // 24(r1)" to save the TOC pointer in their callers stack
+               // frame. Unfortunately (and necessarily) morestack is called before
+               // the function that calls it sets up its frame and so the PLT ends
+               // up smashing the saved TOC pointer for its caller's caller.
+               //
+               // According to the ABI documentation there is a mechanism to avoid
+               // the TOC save that the PLT stub does (put a R_PPC64_TOCSAVE
+               // relocation on the nop after the call to morestack) but at the time
+               // of writing it is not supported at all by gold and my attempt to
+               // use it with ld.bfd caused an internal linker error. So this hack
+               // seems preferable.
+
+               // MOVD $runtime.morestack(SB), R12
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVD
+               p.From.Type = obj.TYPE_MEM
+               p.From.Sym = morestacksym
+               p.From.Name = obj.NAME_GOTREF
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = REG_R12
+
+               // MOVD R12, CTR
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVD
+               p.From.Type = obj.TYPE_REG
+               p.From.Reg = REG_R12
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = REG_CTR
+
+               // BL CTR
+               p = obj.Appendp(ctxt, p)
+               p.As = obj.ACALL
+               p.From.Type = obj.TYPE_REG
+               p.From.Reg = REG_R12
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = REG_CTR
+       } else {
+               // BL   runtime.morestack(SB)
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ABL
+               p.To.Type = obj.TYPE_BRANCH
+               p.To.Sym = morestacksym
+       }
        // BR   start
        p = obj.Appendp(ctxt, p)