1
0
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:
Josh Bleecher Snyder 2015-05-28 17:23:58 -07:00
parent 73d109c509
commit ca19e55f9a

View File

@ -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.