]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: enable framepointer on all arm64
authorRuss Cox <rsc@golang.org>
Wed, 27 Jan 2021 16:34:42 +0000 (11:34 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 19 Feb 2021 00:04:22 +0000 (00:04 +0000)
Frame pointers were already enabled on linux, darwin, ios,
but not freebsd, android, openbsd, netbsd.

But the space was reserved on all platforms, leading to
two different arm64 framepointer conditions in different
parts of the code, one of which had no name
(framepointer_enabled || GOARCH == "arm64",
which might have been "framepointer_space_reserved").

So on the disabled systems, the stack layouts were still
set up for frame pointers and the only difference was not
actually maintaining the FP register in the generated code.

Reduce complexity by just enabling the frame pointer
completely on all the arm64 systems.

This commit passes on freebsd, android, netbsd.
I have not been able to try it on openbsd.

This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.

Change-Id: I83bd23369d24b76db4c6a648fa74f6917819a093
Reviewed-on: https://go-review.googlesource.com/c/go/+/288814
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/dwarfgen/dwarf.go
src/cmd/compile/internal/ssagen/pgen.go
src/cmd/internal/obj/arm64/a.out.go
src/cmd/internal/obj/arm64/obj7.go
src/cmd/internal/objabi/util.go
src/runtime/runtime2.go
src/runtime/traceback.go

index dd22c033ccd57b171f8b13cfbab6b417448682f3..70168cffebf8110c2d67950703474162b154f66b 100644 (file)
@@ -271,8 +271,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
                if base.Ctxt.FixedFrameSize() == 0 {
                        offs -= int64(types.PtrSize)
                }
-               if objabi.Framepointer_enabled || objabi.GOARCH == "arm64" {
-                       // There is a word space for FP on ARM64 even if the frame pointer is disabled
+               if objabi.Framepointer_enabled {
                        offs -= int64(types.PtrSize)
                }
 
index 182f8408cfb40616cef081296bc1af2b393ebaa6..40f07a8d45aad7ada9addfb6681df209450052ad 100644 (file)
@@ -213,8 +213,7 @@ func StackOffset(slot ssa.LocalSlot) int32 {
                if base.Ctxt.FixedFrameSize() == 0 {
                        off -= int64(types.PtrSize)
                }
-               if objabi.Framepointer_enabled || objabi.GOARCH == "arm64" {
-                       // There is a word space for FP on ARM64 even if the frame pointer is disabled
+               if objabi.Framepointer_enabled {
                        off -= int64(types.PtrSize)
                }
        case ir.PPARAM, ir.PPARAMOUT:
index 1d1bea505cd17f9d0406f41911b38cd60452530b..7ab9c1475f7b9a74e542ec158c414d6a989647b2 100644 (file)
@@ -239,7 +239,7 @@ const (
        REGCTXT = REG_R26 // environment for closures
        REGTMP  = REG_R27 // reserved for liblink
        REGG    = REG_R28 // G
-       REGFP   = REG_R29 // frame pointer, unused in the Go toolchain
+       REGFP   = REG_R29 // frame pointer
        REGLINK = REG_R30
 
        // ARM64 uses R31 as both stack pointer and zero register,
index 3b885438520aa2e74f29901637169850fff6224d..8f7648e5d5e2cc33a96f757056d21077c231d701 100644 (file)
@@ -622,25 +622,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 
                        prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
 
-                       if objabi.Framepointer_enabled {
-                               q1 = obj.Appendp(q1, c.newprog)
-                               q1.Pos = p.Pos
-                               q1.As = AMOVD
-                               q1.From.Type = obj.TYPE_REG
-                               q1.From.Reg = REGFP
-                               q1.To.Type = obj.TYPE_MEM
-                               q1.To.Reg = REGSP
-                               q1.To.Offset = -8
-
-                               q1 = obj.Appendp(q1, c.newprog)
-                               q1.Pos = p.Pos
-                               q1.As = ASUB
-                               q1.From.Type = obj.TYPE_CONST
-                               q1.From.Offset = 8
-                               q1.Reg = REGSP
-                               q1.To.Type = obj.TYPE_REG
-                               q1.To.Reg = REGFP
-                       }
+                       // Frame pointer.
+                       q1 = obj.Appendp(q1, c.newprog)
+                       q1.Pos = p.Pos
+                       q1.As = AMOVD
+                       q1.From.Type = obj.TYPE_REG
+                       q1.From.Reg = REGFP
+                       q1.To.Type = obj.TYPE_MEM
+                       q1.To.Reg = REGSP
+                       q1.To.Offset = -8
+
+                       q1 = obj.Appendp(q1, c.newprog)
+                       q1.Pos = p.Pos
+                       q1.As = ASUB
+                       q1.From.Type = obj.TYPE_CONST
+                       q1.From.Offset = 8
+                       q1.Reg = REGSP
+                       q1.To.Type = obj.TYPE_REG
+                       q1.To.Reg = REGFP
 
                        if c.cursym.Func().Text.From.Sym.Wrapper() {
                                // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
@@ -765,28 +764,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                        p.To.Reg = REGSP
                                        p.Spadj = -c.autosize
 
-                                       if objabi.Framepointer_enabled {
-                                               p = obj.Appendp(p, c.newprog)
-                                               p.As = ASUB
-                                               p.From.Type = obj.TYPE_CONST
-                                               p.From.Offset = 8
-                                               p.Reg = REGSP
-                                               p.To.Type = obj.TYPE_REG
-                                               p.To.Reg = REGFP
-                                       }
+                                       // Frame pointer.
+                                       p = obj.Appendp(p, c.newprog)
+                                       p.As = ASUB
+                                       p.From.Type = obj.TYPE_CONST
+                                       p.From.Offset = 8
+                                       p.Reg = REGSP
+                                       p.To.Type = obj.TYPE_REG
+                                       p.To.Reg = REGFP
                                }
                        } else {
                                /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
 
-                               if objabi.Framepointer_enabled {
-                                       p.As = AMOVD
-                                       p.From.Type = obj.TYPE_MEM
-                                       p.From.Reg = REGSP
-                                       p.From.Offset = -8
-                                       p.To.Type = obj.TYPE_REG
-                                       p.To.Reg = REGFP
-                                       p = obj.Appendp(p, c.newprog)
-                               }
+                               // Frame pointer.
+                               p.As = AMOVD
+                               p.From.Type = obj.TYPE_MEM
+                               p.From.Reg = REGSP
+                               p.From.Offset = -8
+                               p.To.Type = obj.TYPE_REG
+                               p.To.Reg = REGFP
+                               p = obj.Appendp(p, c.newprog)
 
                                aoffset := c.autosize
 
@@ -821,6 +818,28 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                }
                        }
 
+                       // If enabled, this code emits 'MOV PC, R27' before every 'MOV LR, PC',
+                       // so that if you are debugging a low-level crash where PC and LR are zero,
+                       // you can look at R27 to see what jumped to the zero.
+                       // This is useful when bringing up Go on a new system.
+                       // (There is similar code in ../ppc64/obj9.go:/if.false.)
+                       const debugRETZERO = false
+                       if debugRETZERO {
+                               if p.As != obj.ARET {
+                                       q = newprog()
+                                       q.Pos = p.Pos
+                                       q.Link = p.Link
+                                       p.Link = q
+                                       p = q
+                               }
+                               p.As = AADR
+                               p.From.Type = obj.TYPE_BRANCH
+                               p.From.Offset = 0
+                               p.To.Type = obj.TYPE_REG
+                               p.To.Reg = REGTMP
+
+                       }
+
                        if p.As != obj.ARET {
                                q = newprog()
                                q.Pos = p.Pos
@@ -866,110 +885,106 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        }
 
                case obj.ADUFFCOPY:
-                       if objabi.Framepointer_enabled {
-                               //  ADR ret_addr, R27
-                               //  STP (FP, R27), -24(SP)
-                               //  SUB 24, SP, FP
-                               //  DUFFCOPY
-                               // ret_addr:
-                               //  SUB 8, SP, FP
-
-                               q1 := p
-                               // copy DUFFCOPY from q1 to q4
-                               q4 := obj.Appendp(p, c.newprog)
-                               q4.Pos = p.Pos
-                               q4.As = obj.ADUFFCOPY
-                               q4.To = p.To
-
-                               q1.As = AADR
-                               q1.From.Type = obj.TYPE_BRANCH
-                               q1.To.Type = obj.TYPE_REG
-                               q1.To.Reg = REG_R27
-
-                               q2 := obj.Appendp(q1, c.newprog)
-                               q2.Pos = p.Pos
-                               q2.As = ASTP
-                               q2.From.Type = obj.TYPE_REGREG
-                               q2.From.Reg = REGFP
-                               q2.From.Offset = int64(REG_R27)
-                               q2.To.Type = obj.TYPE_MEM
-                               q2.To.Reg = REGSP
-                               q2.To.Offset = -24
-
-                               // maintaine FP for DUFFCOPY
-                               q3 := obj.Appendp(q2, c.newprog)
-                               q3.Pos = p.Pos
-                               q3.As = ASUB
-                               q3.From.Type = obj.TYPE_CONST
-                               q3.From.Offset = 24
-                               q3.Reg = REGSP
-                               q3.To.Type = obj.TYPE_REG
-                               q3.To.Reg = REGFP
-
-                               q5 := obj.Appendp(q4, c.newprog)
-                               q5.Pos = p.Pos
-                               q5.As = ASUB
-                               q5.From.Type = obj.TYPE_CONST
-                               q5.From.Offset = 8
-                               q5.Reg = REGSP
-                               q5.To.Type = obj.TYPE_REG
-                               q5.To.Reg = REGFP
-                               q1.From.SetTarget(q5)
-                               p = q5
-                       }
+                       //  ADR ret_addr, R27
+                       //  STP (FP, R27), -24(SP)
+                       //  SUB 24, SP, FP
+                       //  DUFFCOPY
+                       // ret_addr:
+                       //  SUB 8, SP, FP
+
+                       q1 := p
+                       // copy DUFFCOPY from q1 to q4
+                       q4 := obj.Appendp(p, c.newprog)
+                       q4.Pos = p.Pos
+                       q4.As = obj.ADUFFCOPY
+                       q4.To = p.To
+
+                       q1.As = AADR
+                       q1.From.Type = obj.TYPE_BRANCH
+                       q1.To.Type = obj.TYPE_REG
+                       q1.To.Reg = REG_R27
+
+                       q2 := obj.Appendp(q1, c.newprog)
+                       q2.Pos = p.Pos
+                       q2.As = ASTP
+                       q2.From.Type = obj.TYPE_REGREG
+                       q2.From.Reg = REGFP
+                       q2.From.Offset = int64(REG_R27)
+                       q2.To.Type = obj.TYPE_MEM
+                       q2.To.Reg = REGSP
+                       q2.To.Offset = -24
+
+                       // maintain FP for DUFFCOPY
+                       q3 := obj.Appendp(q2, c.newprog)
+                       q3.Pos = p.Pos
+                       q3.As = ASUB
+                       q3.From.Type = obj.TYPE_CONST
+                       q3.From.Offset = 24
+                       q3.Reg = REGSP
+                       q3.To.Type = obj.TYPE_REG
+                       q3.To.Reg = REGFP
+
+                       q5 := obj.Appendp(q4, c.newprog)
+                       q5.Pos = p.Pos
+                       q5.As = ASUB
+                       q5.From.Type = obj.TYPE_CONST
+                       q5.From.Offset = 8
+                       q5.Reg = REGSP
+                       q5.To.Type = obj.TYPE_REG
+                       q5.To.Reg = REGFP
+                       q1.From.SetTarget(q5)
+                       p = q5
 
                case obj.ADUFFZERO:
-                       if objabi.Framepointer_enabled {
-                               //  ADR ret_addr, R27
-                               //  STP (FP, R27), -24(SP)
-                               //  SUB 24, SP, FP
-                               //  DUFFZERO
-                               // ret_addr:
-                               //  SUB 8, SP, FP
-
-                               q1 := p
-                               // copy DUFFZERO from q1 to q4
-                               q4 := obj.Appendp(p, c.newprog)
-                               q4.Pos = p.Pos
-                               q4.As = obj.ADUFFZERO
-                               q4.To = p.To
-
-                               q1.As = AADR
-                               q1.From.Type = obj.TYPE_BRANCH
-                               q1.To.Type = obj.TYPE_REG
-                               q1.To.Reg = REG_R27
-
-                               q2 := obj.Appendp(q1, c.newprog)
-                               q2.Pos = p.Pos
-                               q2.As = ASTP
-                               q2.From.Type = obj.TYPE_REGREG
-                               q2.From.Reg = REGFP
-                               q2.From.Offset = int64(REG_R27)
-                               q2.To.Type = obj.TYPE_MEM
-                               q2.To.Reg = REGSP
-                               q2.To.Offset = -24
-
-                               // maintaine FP for DUFFZERO
-                               q3 := obj.Appendp(q2, c.newprog)
-                               q3.Pos = p.Pos
-                               q3.As = ASUB
-                               q3.From.Type = obj.TYPE_CONST
-                               q3.From.Offset = 24
-                               q3.Reg = REGSP
-                               q3.To.Type = obj.TYPE_REG
-                               q3.To.Reg = REGFP
-
-                               q5 := obj.Appendp(q4, c.newprog)
-                               q5.Pos = p.Pos
-                               q5.As = ASUB
-                               q5.From.Type = obj.TYPE_CONST
-                               q5.From.Offset = 8
-                               q5.Reg = REGSP
-                               q5.To.Type = obj.TYPE_REG
-                               q5.To.Reg = REGFP
-                               q1.From.SetTarget(q5)
-                               p = q5
-                       }
+                       //  ADR ret_addr, R27
+                       //  STP (FP, R27), -24(SP)
+                       //  SUB 24, SP, FP
+                       //  DUFFZERO
+                       // ret_addr:
+                       //  SUB 8, SP, FP
+
+                       q1 := p
+                       // copy DUFFZERO from q1 to q4
+                       q4 := obj.Appendp(p, c.newprog)
+                       q4.Pos = p.Pos
+                       q4.As = obj.ADUFFZERO
+                       q4.To = p.To
+
+                       q1.As = AADR
+                       q1.From.Type = obj.TYPE_BRANCH
+                       q1.To.Type = obj.TYPE_REG
+                       q1.To.Reg = REG_R27
+
+                       q2 := obj.Appendp(q1, c.newprog)
+                       q2.Pos = p.Pos
+                       q2.As = ASTP
+                       q2.From.Type = obj.TYPE_REGREG
+                       q2.From.Reg = REGFP
+                       q2.From.Offset = int64(REG_R27)
+                       q2.To.Type = obj.TYPE_MEM
+                       q2.To.Reg = REGSP
+                       q2.To.Offset = -24
+
+                       // maintain FP for DUFFZERO
+                       q3 := obj.Appendp(q2, c.newprog)
+                       q3.Pos = p.Pos
+                       q3.As = ASUB
+                       q3.From.Type = obj.TYPE_CONST
+                       q3.From.Offset = 24
+                       q3.Reg = REGSP
+                       q3.To.Type = obj.TYPE_REG
+                       q3.To.Reg = REGFP
+
+                       q5 := obj.Appendp(q4, c.newprog)
+                       q5.Pos = p.Pos
+                       q5.As = ASUB
+                       q5.From.Type = obj.TYPE_CONST
+                       q5.From.Offset = 8
+                       q5.Reg = REGSP
+                       q5.To.Type = obj.TYPE_REG
+                       q5.To.Reg = REGFP
+                       q1.From.SetTarget(q5)
+                       p = q5
                }
 
                if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
index a73ab479a16337c49a32b38b2b5fcf272232326c..1f99f8ed5d66279f054ea9f3a95392fa5751f02d 100644 (file)
@@ -137,7 +137,7 @@ func init() {
 }
 
 // Note: must agree with runtime.framepointer_enabled.
-var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin" || GOOS == "ios")
+var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64"
 
 func addexp(s string) {
        // Could do general integer parsing here, but the runtime copy doesn't yet.
index 05520d07b2e0c706ace8ab41cb4a0fa4a4765fd5..5bd283d12f349a8842a8dd70bf719da799ed3418 100644 (file)
@@ -1106,4 +1106,4 @@ var (
 )
 
 // Must agree with cmd/internal/objabi.Framepointer_enabled.
-const framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin" || GOOS == "ios")
+const framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64"
index 7321790b78ac084edad3ab87e64cea34b9d68065..eb185eecd36c238b666e26c0cfec27ec9a2a1d5d 100644 (file)
@@ -275,7 +275,22 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 
                // For architectures with frame pointers, if there's
                // a frame, then there's a saved frame pointer here.
-               if frame.varp > frame.sp && (GOARCH == "amd64" || GOARCH == "arm64") {
+               //
+               // NOTE: This code is not as general as it looks.
+               // On x86, the ABI is to save the frame pointer word at the
+               // top of the stack frame, so we have to back down over it.
+               // On arm64, the frame pointer should be at the bottom of
+               // the stack (with R29 (aka FP) = RSP), in which case we would
+               // not want to do the subtraction here. But we started out without
+               // any frame pointer, and when we wanted to add it, we didn't
+               // want to break all the assembly doing direct writes to 8(RSP)
+               // to set the first parameter to a called function.
+               // So we decided to write the FP link *below* the stack pointer
+               // (with R29 = RSP - 8 in Go functions).
+               // This is technically ABI-compatible but not standard.
+               // And it happens to end up mimicking the x86 layout.
+               // Other architectures may make different decisions.
+               if frame.varp > frame.sp && framepointer_enabled {
                        frame.varp -= sys.PtrSize
                }