]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.power64] cmd/ld, runtime: detect, fix nosplit overflows
authorRuss Cox <rsc@golang.org>
Thu, 14 Aug 2014 19:29:37 +0000 (15:29 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 14 Aug 2014 19:29:37 +0000 (15:29 -0400)
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/121690043

src/cmd/ld/lib.c
src/pkg/runtime/os_linux.c
src/pkg/runtime/string.go
test/nosplit.go

index b4134da3684be191339e03fa97c8704e20485cf5..5db41f9a7177a4e0968475bc177587127942b500 100644 (file)
@@ -1026,7 +1026,7 @@ static LSym *newstack;
 
 enum
 {
-       HasLinkRegister = (thechar == '5'),
+       HasLinkRegister = (thechar == '5' || thechar == '9'),
 };
 
 // TODO: Record enough information in new object files to
@@ -1035,7 +1035,7 @@ enum
 static int
 callsize(void)
 {
-       if(thechar == '5')
+       if(HasLinkRegister)
                return 0;
        return RegSize;
 }
@@ -1046,9 +1046,6 @@ dostkcheck(void)
        Chain ch;
        LSym *s;
 
-       if(thechar == '9')
-               return;
-       
        morestack = linklookup(ctxt, "runtime.morestack", 0);
        newstack = linklookup(ctxt, "runtime.newstack", 0);
 
@@ -1072,19 +1069,19 @@ dostkcheck(void)
                        continue;
 
                if(s->nosplit) {
-               ctxt->cursym = s;
-               ch.sym = s;
-               stkcheck(&ch, 0);
-       }
+                       ctxt->cursym = s;
+                       ch.sym = s;
+                       stkcheck(&ch, 0);
+               }
        }
        for(s = ctxt->textp; s != nil; s = s->next) {
                if(!s->nosplit) {
-               ctxt->cursym = s;
-               ch.sym = s;
-               stkcheck(&ch, 0);
+                       ctxt->cursym = s;
+                       ch.sym = s;
+                       stkcheck(&ch, 0);
+               }
        }
 }
-}
 
 static int
 stkcheck(Chain *up, int depth)
@@ -1102,7 +1099,7 @@ stkcheck(Chain *up, int depth)
        // function at top of safe zone once.
        if(limit == StackLimit-callsize()) {
                if(s->stkcheck)
-               return 0;
+                       return 0;
                s->stkcheck = 1;
        }
        
@@ -1161,8 +1158,8 @@ stkcheck(Chain *up, int depth)
                                // to StackLimit beyond the frame size.
                                if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
                                        limit = StackLimit + s->locals;
-                                       if(thechar == '5')
-                                               limit += 4; // saved LR
+                                       if(HasLinkRegister)
+                                               limit += RegSize;
                                }
                                break;
 
@@ -1181,7 +1178,7 @@ stkcheck(Chain *up, int depth)
                                break;
                        }
                }
-               }
+       }
                
        return 0;
 }
@@ -1210,7 +1207,7 @@ stkprint(Chain *ch, int limit)
                else
                        print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
        } else {
-               stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
+               stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
                if(!HasLinkRegister)
                        print("\t%d\ton entry to %s\n", ch->limit, name);
        }
index 1751ea83b2f18ef3fdc50a57cf9ed20eb521eda7..8aadee721571c4ef245fe504c87fbbc590cd03a7 100644 (file)
@@ -49,9 +49,22 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
                runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
                return;
        }
-       // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
+
+       // It's difficult to live within the no-split stack limits here.
+       // On ARM and 386, a 64-bit divide invokes a general software routine
+       // that needs more stack than we can afford. So we use timediv instead.
+       // But on real 64-bit systems, where words are larger but the stack limit
+       // is not, even timediv is too heavy, and we really need to use just an
+       // ordinary machine instruction.
+       // Sorry for the #ifdef.
+       // For what it's worth, the #ifdef eliminated an implicit little-endian assumption.
+#ifdef _64BIT
+       ts.tv_sec = ns / 1000000000LL;
+       ts.tv_nsec = ns % 1000000000LL;
+#else
        ts.tv_nsec = 0;
        ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
+#endif
        runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
 }
 
index c5b0917482c9689ea660667c45e60ee28b4d0f18..69874e909b216b614341aff5be6ee8094ab6ba04 100644 (file)
@@ -39,22 +39,18 @@ func concatstrings(a []string) string {
        return s
 }
 
-//go:nosplit
 func concatstring2(a [2]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring3(a [3]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring4(a [4]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring5(a [5]string) string {
        return concatstrings(a[:])
 }
index de279efdd409c845ed1a605d5d103fa82e96ccee..b5399ad38d4ea545ca617518f87e2ea360344586 100644 (file)
@@ -126,8 +126,9 @@ main 136 nosplit; REJECT
 # Calling a nosplit function from a nosplit function requires
 # having room for the saved caller PC and the called frame.
 # Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
+# Because Power64 doesn't save LR in the leaf, it gets an extra 8 bytes.
 main 112 nosplit call f; f 0 nosplit
-main 116 nosplit call f; f 0 nosplit; REJECT amd64
+main 116 nosplit call f; f 0 nosplit
 main 120 nosplit call f; f 0 nosplit; REJECT amd64
 main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
 main 128 nosplit call f; f 0 nosplit; REJECT
@@ -136,8 +137,8 @@ main 136 nosplit call f; f 0 nosplit; REJECT
 
 # Calling a splitting function from a nosplit function requires
 # having room for the saved caller PC of the call but also the
-# saved caller PC for the call to morestack. Again the ARM works
-# in less space.
+# saved caller PC for the call to morestack.
+# Again the ARM and Power64 work in less space.
 main 104 nosplit call f; f 0 call f
 main 108 nosplit call f; f 0 call f
 main 112 nosplit call f; f 0 call f; REJECT amd64
@@ -235,7 +236,7 @@ TestCases:
                switch goarch {
                case "power64", "power64le":
                        ptrSize = 8
-                       fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n#define RET RETURN\n")
+                       fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n#define RET RETURN\n")
                case "arm":
                        fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
                case "amd64":