Skip to content

Commit 767e065

Browse files
committed
cmd/link: fix nosplit stack overflow checks
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 <[email protected]>
1 parent 4212205 commit 767e065

File tree

1 file changed

+12
-35
lines changed
  • src/cmd/link/internal/ld

1 file changed

+12
-35
lines changed

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

+12-35
Original file line numberDiff line numberDiff line change
@@ -1465,10 +1465,7 @@ type Chain struct {
14651465
limit int // limit on entry to sym
14661466
}
14671467

1468-
var (
1469-
morestack *LSym
1470-
newstack *LSym
1471-
)
1468+
var morestack *LSym
14721469

14731470
// TODO: Record enough information in new object files to
14741471
// allow stack checks here.
@@ -1488,7 +1485,6 @@ func dostkcheck() {
14881485
var ch Chain
14891486

14901487
morestack = Linklookup(Ctxt, "runtime.morestack", 0)
1491-
newstack = Linklookup(Ctxt, "runtime.newstack", 0)
14921488

14931489
// Every splitting function ensures that there are at least StackLimit
14941490
// bytes available below SP when the splitting prologue finishes.
@@ -1533,7 +1529,8 @@ func stkcheck(up *Chain, depth int) int {
15331529

15341530
// Don't duplicate work: only need to consider each
15351531
// function at top of safe zone once.
1536-
if limit == obj.StackLimit-callsize() {
1532+
top := limit == obj.StackLimit-callsize()
1533+
if top {
15371534
if s.Stkcheck != 0 {
15381535
return 0
15391536
}
@@ -1571,39 +1568,21 @@ func stkcheck(up *Chain, depth int) int {
15711568
var ch Chain
15721569
ch.up = up
15731570

1574-
// Check for a call to morestack anywhere and treat it
1575-
// as occurring at function entry.
1576-
// The decision about whether to call morestack occurs
1577-
// in the prolog, but the call site is near the end
1578-
// of the function on some architectures.
1579-
// This is needed because the stack check is flow-insensitive,
1580-
// so it incorrectly thinks the call to morestack happens wherever it shows up.
1581-
// This check will be wrong if there are any hand-inserted calls to morestack.
1582-
// There are not any now, nor should there ever be.
1583-
for _, r := range s.R {
1584-
if r.Sym == nil || !strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
1585-
continue
1586-
}
1587-
// Ignore non-calls to morestack, such as the jump to morestack
1588-
// found in the implementation of morestack_noctxt.
1589-
switch r.Type {
1590-
default:
1591-
continue
1592-
case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
1593-
}
1594-
1571+
if s.Nosplit == 0 {
15951572
// Ensure we have enough stack to call morestack.
15961573
ch.limit = limit - callsize()
1597-
ch.sym = r.Sym
1574+
ch.sym = morestack
15981575
if stkcheck(&ch, depth+1) < 0 {
15991576
return -1
16001577
}
1601-
// Bump up the limit.
1578+
if !top {
1579+
return 0
1580+
}
1581+
// Raise limit to allow frame.
16021582
limit = int(obj.StackLimit + s.Locals)
16031583
if haslinkregister() {
16041584
limit += Thearch.Regsize
16051585
}
1606-
break // there can be only one
16071586
}
16081587

16091588
// Walk through sp adjustments in function, consuming relocs.
@@ -1628,11 +1607,6 @@ func stkcheck(up *Chain, depth int) int {
16281607
switch r.Type {
16291608
// Direct call.
16301609
case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
1631-
// We handled calls to morestack already.
1632-
if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
1633-
continue
1634-
}
1635-
16361610
ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
16371611
ch.sym = r.Sym
16381612
if stkcheck(&ch, depth+1) < 0 {
@@ -1670,6 +1644,9 @@ func stkprint(ch *Chain, limit int) {
16701644

16711645
if ch.sym != nil {
16721646
name = ch.sym.Name
1647+
if ch.sym.Nosplit != 0 {
1648+
name += " (nosplit)"
1649+
}
16731650
} else {
16741651
name = "function pointer"
16751652
}

0 commit comments

Comments
 (0)