aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Hudson-Doyle <michael.hudson@canonical.com>2015-10-16 20:50:59 +1300
committerMichael Hudson-Doyle <michael.hudson@canonical.com>2015-11-13 00:36:22 +0000
commit64fbca41c8777b2b03f7e545be3bea34862ecf8f (patch)
tree1a73198aeeba7a109fd9ff010313fc6231b4942b /src
parent2ac993107fcae841ca6e81ad75e88d8b5973a115 (diff)
downloadgo-64fbca41c8777b2b03f7e545be3bea34862ecf8f.tar.xz
cmd/internal/obj/ppc64: avoid calling morestack via a PLT when dynamically linking
Change-Id: Ie79f72786b1d7154f1910e717a0faf354b913b89 Reviewed-on: https://go-review.googlesource.com/15970 Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/internal/obj/ppc64/obj9.go59
1 files changed, 51 insertions, 8 deletions
diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go
index a876b99a76..696f6e5834 100644
--- a/src/cmd/internal/obj/ppc64/obj9.go
+++ b/src/cmd/internal/obj/ppc64/obj9.go
@@ -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)