]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: fix nosplit stack overflow checks
authorRuss Cox <rsc@golang.org>
Wed, 29 Jul 2015 19:07:35 +0000 (15:07 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 29 Jul 2015 21:36:16 +0000 (21:36 +0000)
The nosplit stack overflow checks were confused about morestack.
The comment about not having correct SP information at the call
to morestack was true, but that was a real bug, not something to
work around. I fixed that problem in CL 12144. With that fixed,
no need to special-case morestack in the way done here.

This cleanup and simplification of the code was the first step
to fixing a bug that happened when I started working on the
arm64 frame size adjustments, but the cleanup was sufficient
to make the bug go away.

For #9880.

Change-Id: I16b69a5c16b6b8cb4090295d3029c42d606e3b9b
Reviewed-on: https://go-review.googlesource.com/12846
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/link/internal/ld/lib.go

index 728e78260cae459f6712cf821d671ddd269b2c73..8ccbec9dd6342c35ae7e7482721bfc715de60299 100644 (file)
@@ -1465,10 +1465,7 @@ type Chain struct {
        limit int // limit on entry to sym
 }
 
-var (
-       morestack *LSym
-       newstack  *LSym
-)
+var morestack *LSym
 
 // TODO: Record enough information in new object files to
 // allow stack checks here.
@@ -1488,7 +1485,6 @@ func dostkcheck() {
        var ch Chain
 
        morestack = Linklookup(Ctxt, "runtime.morestack", 0)
-       newstack = Linklookup(Ctxt, "runtime.newstack", 0)
 
        // Every splitting function ensures that there are at least StackLimit
        // bytes available below SP when the splitting prologue finishes.
@@ -1533,7 +1529,8 @@ func stkcheck(up *Chain, depth int) int {
 
        // Don't duplicate work: only need to consider each
        // function at top of safe zone once.
-       if limit == obj.StackLimit-callsize() {
+       top := limit == obj.StackLimit-callsize()
+       if top {
                if s.Stkcheck != 0 {
                        return 0
                }
@@ -1571,39 +1568,21 @@ func stkcheck(up *Chain, depth int) int {
        var ch Chain
        ch.up = up
 
-       // Check for a call to morestack anywhere and treat it
-       // as occurring at function entry.
-       // The decision about whether to call morestack occurs
-       // in the prolog, but the call site is near the end
-       // of the function on some architectures.
-       // This is needed because the stack check is flow-insensitive,
-       // so it incorrectly thinks the call to morestack happens wherever it shows up.
-       // This check will be wrong if there are any hand-inserted calls to morestack.
-       // There are not any now, nor should there ever be.
-       for _, r := range s.R {
-               if r.Sym == nil || !strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
-                       continue
-               }
-               // Ignore non-calls to morestack, such as the jump to morestack
-               // found in the implementation of morestack_noctxt.
-               switch r.Type {
-               default:
-                       continue
-               case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
-               }
-
+       if s.Nosplit == 0 {
                // Ensure we have enough stack to call morestack.
                ch.limit = limit - callsize()
-               ch.sym = r.Sym
+               ch.sym = morestack
                if stkcheck(&ch, depth+1) < 0 {
                        return -1
                }
-               // Bump up the limit.
+               if !top {
+                       return 0
+               }
+               // Raise limit to allow frame.
                limit = int(obj.StackLimit + s.Locals)
                if haslinkregister() {
                        limit += Thearch.Regsize
                }
-               break // there can be only one
        }
 
        // Walk through sp adjustments in function, consuming relocs.
@@ -1628,11 +1607,6 @@ func stkcheck(up *Chain, depth int) int {
                        switch r.Type {
                        // Direct call.
                        case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
-                               // We handled calls to morestack already.
-                               if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
-                                       continue
-                               }
-
                                ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
                                ch.sym = r.Sym
                                if stkcheck(&ch, depth+1) < 0 {
@@ -1670,6 +1644,9 @@ func stkprint(ch *Chain, limit int) {
 
        if ch.sym != nil {
                name = ch.sym.Name
+               if ch.sym.Nosplit != 0 {
+                       name += " (nosplit)"
+               }
        } else {
                name = "function pointer"
        }