mirror of https://github.com/golang/go.git
89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
// Copyright 2022 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package ld
|
|
|
|
import (
|
|
"fmt"
|
|
"internal/testenv"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
// See also $GOROOT/test/nosplit.go for multi-platform edge case tests.
|
|
|
|
func TestStackCheckOutput(t *testing.T) {
|
|
testenv.MustHaveGoBuild(t)
|
|
t.Parallel()
|
|
|
|
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", os.DevNull, "./testdata/stackcheck")
|
|
// The rules for computing frame sizes on all of the
|
|
// architectures are complicated, so just do this on amd64.
|
|
cmd.Env = append(os.Environ(), "GOARCH=amd64", "GOOS=linux")
|
|
outB, err := cmd.CombinedOutput()
|
|
|
|
if err == nil {
|
|
t.Fatalf("expected link to fail")
|
|
}
|
|
out := string(outB)
|
|
|
|
t.Logf("linker output:\n%s", out)
|
|
|
|
// Get expected limit.
|
|
limitRe := regexp.MustCompile("nosplit stack over ([0-9]+) byte limit")
|
|
m := limitRe.FindStringSubmatch(out)
|
|
if m == nil {
|
|
t.Fatalf("no overflow errors in output")
|
|
}
|
|
limit, _ := strconv.Atoi(m[1])
|
|
|
|
wantMap := map[string]string{
|
|
"main.startSelf": fmt.Sprintf(
|
|
`main.startSelf<0>
|
|
grows 1008 bytes
|
|
%d bytes over limit
|
|
`, 1008-limit),
|
|
"main.startChain": fmt.Sprintf(
|
|
`main.startChain<0>
|
|
grows 32 bytes, calls main.chain0<0>
|
|
grows 48 bytes, calls main.chainEnd<0>
|
|
grows 1008 bytes
|
|
%d bytes over limit
|
|
grows 32 bytes, calls main.chain2<0>
|
|
grows 80 bytes, calls main.chainEnd<0>
|
|
grows 1008 bytes
|
|
%d bytes over limit
|
|
`, 32+48+1008-limit, 32+80+1008-limit),
|
|
"main.startRec": `main.startRec<0>
|
|
grows 8 bytes, calls main.startRec0<0>
|
|
grows 8 bytes, calls main.startRec<0>
|
|
infinite cycle
|
|
`,
|
|
}
|
|
|
|
// Parse stanzas
|
|
stanza := regexp.MustCompile(`^(.*): nosplit stack over [0-9]+ byte limit\n(.*\n(?: .*\n)*)`)
|
|
// Strip comments from cmd/go
|
|
out = regexp.MustCompile(`(?m)^#.*\n`).ReplaceAllString(out, "")
|
|
for len(out) > 0 {
|
|
m := stanza.FindStringSubmatch(out)
|
|
if m == nil {
|
|
t.Fatalf("unexpected output:\n%s", out)
|
|
}
|
|
out = out[len(m[0]):]
|
|
fn := m[1]
|
|
got := m[2]
|
|
|
|
want, ok := wantMap[fn]
|
|
if !ok {
|
|
t.Errorf("unexpected function: %s", fn)
|
|
} else if want != got {
|
|
t.Errorf("want:\n%sgot:\n%s", want, got)
|
|
}
|
|
}
|
|
}
|