Skip to content

Commit ca19e55

Browse files
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 73d109c commit ca19e55

File tree

1 file changed

+41
-11
lines changed
  • src/cmd/link/internal/ld

1 file changed

+41
-11
lines changed

src/cmd/link/internal/ld/lib.go

+41-11
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,41 @@ func stkcheck(up *Chain, depth int) int {
15291529
var ch Chain
15301530
ch.up = up
15311531

1532+
// Check for a call to morestack anywhere and treat it
1533+
// as occurring at function entry.
1534+
// The decision about whether to call morestack occurs
1535+
// in the prolog, but the call site is near the end
1536+
// of the function on some architectures.
1537+
// This is needed because the stack check is flow-insensitive,
1538+
// so it incorrectly thinks the call to morestack happens wherever it shows up.
1539+
// This check will be wrong if there are any hand-inserted calls to morestack.
1540+
// There are not any now, nor should there ever be.
1541+
for _, r := range s.R {
1542+
if r.Sym == nil || !strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
1543+
continue
1544+
}
1545+
// Ignore non-calls to morestack, such as the jump to morestack
1546+
// found in the implementation of morestack_noctxt.
1547+
switch r.Type {
1548+
default:
1549+
continue
1550+
case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
1551+
}
1552+
1553+
// Ensure we have enough stack to call morestack.
1554+
ch.limit = limit - callsize()
1555+
ch.sym = r.Sym
1556+
if stkcheck(&ch, depth+1) < 0 {
1557+
return -1
1558+
}
1559+
// Bump up the limit.
1560+
limit = int(obj.StackLimit + s.Locals)
1561+
if haslinkregister() {
1562+
limit += Thearch.Regsize
1563+
}
1564+
break // there can be only one
1565+
}
1566+
15321567
// Walk through sp adjustments in function, consuming relocs.
15331568
ri := 0
15341569

@@ -1551,23 +1586,18 @@ func stkcheck(up *Chain, depth int) int {
15511586
switch r.Type {
15521587
// Direct call.
15531588
case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
1554-
ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
1589+
// We handled calls to morestack already.
1590+
if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
1591+
continue
1592+
}
15551593

1594+
ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
15561595
ch.sym = r.Sym
15571596
if stkcheck(&ch, depth+1) < 0 {
15581597
return -1
15591598
}
15601599

1561-
// If this is a call to morestack, we've just raised our limit back
1562-
// to StackLimit beyond the frame size.
1563-
if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
1564-
limit = int(obj.StackLimit + s.Locals)
1565-
if haslinkregister() {
1566-
limit += Thearch.Regsize
1567-
}
1568-
}
1569-
1570-
// Indirect call. Assume it is a call to a splitting function,
1600+
// Indirect call. Assume it is a call to a splitting function,
15711601
// so we have to make sure it can call morestack.
15721602
// Arrange the data structures to report both calls, so that
15731603
// if there is an error, stkprint shows all the steps involved.

0 commit comments

Comments
 (0)