1
2
3
4
5 package ld
6
7 import (
8 "fmt"
9 "internal/testenv"
10 "os"
11 "regexp"
12 "strconv"
13 "testing"
14 )
15
16
17
18 func TestStackCheckOutput(t *testing.T) {
19 testenv.MustHaveGoBuild(t)
20 t.Parallel()
21
22 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", os.DevNull, "./testdata/stackcheck")
23
24
25 cmd.Env = append(os.Environ(), "GOARCH=amd64", "GOOS=linux")
26 outB, err := cmd.CombinedOutput()
27
28 if err == nil {
29 t.Fatalf("expected link to fail")
30 }
31 out := string(outB)
32
33 t.Logf("linker output:\n%s", out)
34
35
36 limitRe := regexp.MustCompile(`nosplit stack over (\d+) byte limit`)
37 m := limitRe.FindStringSubmatch(out)
38 if m == nil {
39 t.Fatalf("no overflow errors in output")
40 }
41 limit, _ := strconv.Atoi(m[1])
42
43 wantMap := map[string]string{
44 "main.startSelf": fmt.Sprintf(
45 `main.startSelf<0>
46 grows 1008 bytes
47 %d bytes over limit
48 `, 1008-limit),
49 "main.startChain": fmt.Sprintf(
50 `main.startChain<0>
51 grows 32 bytes, calls main.chain0<0>
52 grows 48 bytes, calls main.chainEnd<0>
53 grows 1008 bytes
54 %d bytes over limit
55 grows 32 bytes, calls main.chain2<0>
56 grows 80 bytes, calls main.chainEnd<0>
57 grows 1008 bytes
58 %d bytes over limit
59 `, 32+48+1008-limit, 32+80+1008-limit),
60 "main.startRec": `main.startRec<0>
61 grows 8 bytes, calls main.startRec0<0>
62 grows 8 bytes, calls main.startRec<0>
63 infinite cycle
64 `,
65 }
66
67
68 stanza := regexp.MustCompile(`^(.*): nosplit stack over \d+ byte limit\n(.*\n(?: .*\n)*)`)
69
70 out = regexp.MustCompile(`(?m)^#.*\n`).ReplaceAllString(out, "")
71 for len(out) > 0 {
72 m := stanza.FindStringSubmatch(out)
73 if m == nil {
74 t.Fatalf("unexpected output:\n%s", out)
75 }
76 out = out[len(m[0]):]
77 fn := m[1]
78 got := m[2]
79
80 want, ok := wantMap[fn]
81 if !ok {
82 t.Errorf("unexpected function: %s", fn)
83 } else if want != got {
84 t.Errorf("want:\n%sgot:\n%s", want, got)
85 }
86 }
87 }
88
View as plain text