mirror of
https://github.com/golang/go
synced 2024-11-18 08:14:41 -07:00
cmd/link: make stkcheck more flexible
stkcheck is flow-insensitive: It processes calls in PC order. Since morestack was always the first call in a function, it was a safe, conservative approximation to simply adjust stack space as we went, recognizing morestack when it showed up. Subsequent CLS will rearrange the function prologue; morestack may no longer be the first call in a function. Introducing flow-sensitivity to stkcheck would allow this, and possibly allow a smaller stackguard. It is also a high risk change and possibly expensive. Instead, assume that all calls to morestack occur as part of the function prologue, no matter where they are located in the program text. Updates #10587. Change-Id: I4dcdd4256a980fc4bc433a68a10989ff57f7034f Reviewed-on: https://go-review.googlesource.com/10496 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
73d109c509
commit
ca19e55f9a
@ -1529,6 +1529,41 @@ 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:
|
||||
}
|
||||
|
||||
// Ensure we have enough stack to call morestack.
|
||||
ch.limit = limit - callsize()
|
||||
ch.sym = r.Sym
|
||||
if stkcheck(&ch, depth+1) < 0 {
|
||||
return -1
|
||||
}
|
||||
// Bump up the limit.
|
||||
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.
|
||||
ri := 0
|
||||
|
||||
@ -1551,23 +1586,18 @@ 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:
|
||||
ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
|
||||
// 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 {
|
||||
return -1
|
||||
}
|
||||
|
||||
// If this is a call to morestack, we've just raised our limit back
|
||||
// to StackLimit beyond the frame size.
|
||||
if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
|
||||
limit = int(obj.StackLimit + s.Locals)
|
||||
if haslinkregister() {
|
||||
limit += Thearch.Regsize
|
||||
}
|
||||
}
|
||||
|
||||
// Indirect call. Assume it is a call to a splitting function,
|
||||
// Indirect call. Assume it is a call to a splitting function,
|
||||
// so we have to make sure it can call morestack.
|
||||
// Arrange the data structures to report both calls, so that
|
||||
// if there is an error, stkprint shows all the steps involved.
|
||||
|
Loading…
Reference in New Issue
Block a user