]> Cypherpunks repositories - gostls13.git/commitdiff
cgo: fix g0 stack guard
authorDmitriy Vyukov <dvyukov@google.com>
Wed, 9 Nov 2011 20:11:48 +0000 (23:11 +0300)
committerDmitriy Vyukov <dvyukov@google.com>
Wed, 9 Nov 2011 20:11:48 +0000 (23:11 +0300)
Fixes crash when cgo consumes more than 8K
of stack and makes a callback.

Fixes #1328.

R=golang-dev, rogpeppe, rsc
CC=golang-dev, mpimenov
https://golang.org/cl/5371042

12 files changed:
misc/cgo/test/callback_c.c
src/pkg/runtime/386/asm.s
src/pkg/runtime/amd64/asm.s
src/pkg/runtime/cgo/darwin_386.c
src/pkg/runtime/cgo/darwin_amd64.c
src/pkg/runtime/cgo/freebsd_386.c
src/pkg/runtime/cgo/freebsd_amd64.c
src/pkg/runtime/cgo/linux_386.c
src/pkg/runtime/cgo/linux_amd64.c
src/pkg/runtime/cgo/linux_arm.c
src/pkg/runtime/cgo/windows_386.c
src/pkg/runtime/cgo/windows_amd64.c

index 5983a5e11542d924de8beb96508bcc1bd65e1712..c296d70e0577d6639da359b956ecf22ea839b175 100644 (file)
@@ -8,5 +8,10 @@
 void
 callback(void *f)
 {
+       // use some stack space
+       volatile char data[64*1024];
+
+       data[0] = 0;
        goCallback(f);
+        data[sizeof(data)-1] = 0;
 }
index bafef01c7eb3dc8490bf784d3e5bdb336d494047..470463925e6fed233b488872a8aa02df8317db16 100644 (file)
@@ -26,12 +26,14 @@ TEXT _rt0_386(SB),7,$0
        // we set up GS ourselves.
        MOVL    initcgo(SB), AX
        TESTL   AX, AX
-       JZ      4(PC)
+       JZ      needtls
+       PUSHL   $runtime·g0(SB)
        CALL    AX
+       POPL    AX
        // skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
        CMPL runtime·iswindows(SB), $0
        JEQ ok
-
+needtls:
        // skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
        CMPL    runtime·isplan9(SB), $1
        JEQ     ok
@@ -58,9 +60,15 @@ ok:
        MOVL    CX, m_g0(AX)
 
        // create istack out of the OS stack
+       // if there is an initcgo, it had setup stackguard for us
+       MOVL    initcgo(SB), AX
+       TESTL   AX, AX
+       JNZ     stackok
        LEAL    (-64*1024+104)(SP), AX  // TODO: 104?
        MOVL    AX, g_stackguard(CX)
+stackok:
        MOVL    SP, g_stackbase(CX)
+
        CALL    runtime·emptyfunc(SB)  // fault if stack check is wrong
 
        // convention is D is always cleared
index 866e083106a2bdfc839cf6109d55d98caf92ca4f..109b95eba80bfb37a2581bd4fe7b8a57b4697621 100644 (file)
@@ -17,6 +17,7 @@ TEXT _rt0_amd64(SB),7,$-8
        MOVQ    initcgo(SB), AX
        TESTQ   AX, AX
        JZ      needtls
+       LEAQ    runtime·g0(SB), DI
        CALL    AX
        CMPL    runtime·iswindows(SB), $0
        JEQ ok
@@ -44,8 +45,13 @@ ok:
        MOVQ    CX, m_g0(AX)
 
        // create istack out of the given (operating system) stack
+       // if there is an initcgo, it had setup stackguard for us
+       MOVQ    initcgo(SB), AX
+       TESTQ   AX, AX
+       JNZ     stackok
        LEAQ    (-8192+104)(SP), AX
        MOVQ    AX, g_stackguard(CX)
+stackok:
        MOVQ    SP, g_stackbase(CX)
 
        CLD                             // convention is D is always left cleared
index 6d4e259be0366b2c3b62fc12db9edcd660cc17ea..dbc3d31f9cb2f4be3fa93d80da19cfe361187a4c 100644 (file)
@@ -100,12 +100,20 @@ inittls(void)
 }
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
+
        inittls();
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index 3471044c014ff6b509ed9ef4a2e7e53aaee08953..48ee83bc8b7505ea835dc33a2d9d04bd4cbdee10 100644 (file)
@@ -70,12 +70,20 @@ inittls(void)
 }
 
 void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
+
        inittls();
 }
 
-void (*initcgo) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index ae53201b41e337ec0728a0f4f7dabad5a494aae8..ad9468730771f9f5d6939204a59b2c2b9a167d32 100644 (file)
@@ -8,11 +8,18 @@
 static void* threadentry(void*);
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index 5afc1dfeafbaadb90da0aa11719163655c894067..b18d1bc67da91bdb2e20e1a873db5fd74e5eacc6 100644 (file)
@@ -8,11 +8,18 @@
 static void* threadentry(void*);
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index e9df5ffdccbc2fe6e9e6319daf290a4b48ad2b0c..8401a75caa82a090090676f31ebd3a2d8d02e672 100644 (file)
@@ -9,11 +9,18 @@
 static void *threadentry(void*);
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
 }
 
-void (*initcgo) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index d9b8b37061020e2503ee2005aa66760f9e32a11d..6ce3333a858fc7adb2cac3c2d270a6fb9cf2e8e1 100644 (file)
@@ -3,16 +3,24 @@
 // license that can be found in the LICENSE file.
 
 #include <pthread.h>
+#include <string.h> // strerror
 #include "libcgo.h"
 
 static void* threadentry(void*);
 
 void
-xinitcgo(void)
+xinitcgo(G* g)
 {
+       pthread_attr_t attr;
+       size_t size;
+
+       pthread_attr_init(&attr);
+       pthread_attr_getstacksize(&attr, &size);
+       g->stackguard = (uintptr)&attr - size + 4096;
+       pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index e556c433ce433a03dde5e8e9d47dfe526632ae99..8397c75bb8ace1ae5e485890caa282eecd116512 100644 (file)
@@ -5,11 +5,12 @@
 #include "libcgo.h"
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       // unimplemented
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index f39309cb1b19063e602002f54cdc7b5c8de27712..96aea07128db699dc357938118a1363e4df61077 100644 (file)
@@ -13,11 +13,13 @@ static void *threadentry(void*);
 #define STACKSIZE (1*1024*1024)
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       int tmp;
+       g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)
index e8313e250aa78f4b16b31cad0ad0f24bbfa00bd1..6d31845ce6f9dd5648d5f982d3d14715a94bce49 100644 (file)
@@ -13,11 +13,13 @@ static void *threadentry(void*);
 #define STACKSIZE (2*1024*1024)
 
 static void
-xinitcgo(void)
+xinitcgo(G *g)
 {
+       int tmp;
+       g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
 }
 
-void (*initcgo)(void) = xinitcgo;
+void (*initcgo)(G*) = xinitcgo;
 
 void
 libcgo_sys_thread_start(ThreadStart *ts)