]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/6l, cmd/8l: emit no-ops to separate zero-stack funcs from nosplits.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 26 Nov 2012 20:51:48 +0000 (21:51 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 26 Nov 2012 20:51:48 +0000 (21:51 +0100)
The stack overflow checker in the linker uses the spadj field
to determine whether stack space will be large enough or not.
When spadj=0, the checker treats the function as a nosplit
and emits an error although the program is correct.

Also enable the stack checker in 8l.

Fixes #4316.

R=rsc, golang-dev
CC=golang-dev
https://golang.org/cl/6855088

src/cmd/6l/pass.c
src/cmd/8l/obj.c
src/cmd/8l/pass.c
test/fixedbugs/issue4316.go [new file with mode: 0644]

index c2d5dc1067879a6446c21421474ecb05903e55ea..043048e8a06807a26d461db692f203cf1b72389b 100644 (file)
@@ -604,6 +604,16 @@ dostkoff(void)
                        p->spadj = autoffset;
                        if(q != P)
                                q->pcond = p;
+               } else {
+                       // zero-byte stack adjustment.
+                       // Insert a fake non-zero adjustment so that stkcheck can
+                       // recognize the end of the stack-splitting prolog.
+                       p = appendp(p);
+                       p->as = ANOP;
+                       p->spadj = -PtrSize;
+                       p = appendp(p);
+                       p->as = ANOP;
+                       p->spadj = PtrSize;
                }
                deltasp = autoffset;
 
index eebf9fcfe59b2fe2d98136d015954bd7101bbca6..66f1205e5a479c20286e6d98c5e0db6b7c940f26 100644 (file)
@@ -308,6 +308,7 @@ main(int argc, char *argv[])
        if(HEADTYPE == Hwindows)
                dope();
        dostkoff();
+       dostkcheck();
        if(debug['p'])
                if(debug['1'])
                        doprof1();
index 27d8d4ee2a48550bdee1be010b534c17fc31af17..6cf3009e2cc8f284989ba320d928115ce4cfb7d9 100644 (file)
@@ -580,6 +580,16 @@ dostkoff(void)
                        p->spadj = autoffset;
                        if(q != P)
                                q->pcond = p;
+               } else {
+                       // zero-byte stack adjustment.
+                       // Insert a fake non-zero adjustment so that stkcheck can
+                       // recognize the end of the stack-splitting prolog.
+                       p = appendp(p);
+                       p->as = ANOP;
+                       p->spadj = -PtrSize;
+                       p = appendp(p);
+                       p->as = ANOP;
+                       p->spadj = PtrSize;
                }
                deltasp = autoffset;
                
diff --git a/test/fixedbugs/issue4316.go b/test/fixedbugs/issue4316.go
new file mode 100644 (file)
index 0000000..bb18a08
--- /dev/null
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2012 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.
+
+// Issue 4316: the stack overflow check in the linker
+// is confused when it encounters a split-stack function
+// that needs 0 bytes of stack space.
+
+package main
+
+type Peano *Peano
+
+func makePeano(n int) *Peano {
+       if n == 0 {
+               return nil
+       }
+       p := Peano(makePeano(n - 1))
+       return &p
+}
+
+var countArg Peano
+var countResult int
+
+func countPeano() {
+       if countArg == nil {
+               countResult = 0
+               return
+       }
+       countArg = *countArg
+       countPeano()
+       countResult++
+}
+
+var s = "(())"
+var pT = 0
+
+func p() {
+       if pT >= len(s) {
+               return
+       }
+       if s[pT] == '(' {
+               pT += 1
+               p()
+               if pT < len(s) && s[pT] == ')' {
+                       pT += 1
+               } else {
+                       return
+               }
+               p()
+       }
+}
+
+func main() {
+       countArg = makePeano(4096)
+       countPeano()
+       if countResult != 4096 {
+               println("countResult =", countResult)
+               panic("countResult != 4096")
+       }
+
+       p()
+}