| | |
| | |
| | |
| |
|
| | package ld |
| |
|
| | import ( |
| | "fmt" |
| | "internal/testenv" |
| | "os" |
| | "regexp" |
| | "strconv" |
| | "testing" |
| | ) |
| |
|
| | |
| |
|
| | func TestStackCheckOutput(t *testing.T) { |
| | testenv.MustHaveGoBuild(t) |
| | t.Parallel() |
| |
|
| | cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", os.DevNull, "./testdata/stackcheck") |
| | |
| | |
| | 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) |
| |
|
| | |
| | limitRe := regexp.MustCompile(`nosplit stack over (\d+) 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 |
| | `, |
| | } |
| |
|
| | |
| | stanza := regexp.MustCompile(`^(.*): nosplit stack over \d+ byte limit\n(.*\n(?: .*\n)*)`) |
| | |
| | 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) |
| | } |
| | } |
| | } |
| |
|