Commit fbfed491 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

cgo: fix g0 stack guard

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
parent 98321731
...@@ -8,5 +8,10 @@ ...@@ -8,5 +8,10 @@
void void
callback(void *f) callback(void *f)
{ {
// use some stack space
volatile char data[64*1024];
data[0] = 0;
goCallback(f); goCallback(f);
data[sizeof(data)-1] = 0;
} }
...@@ -26,12 +26,14 @@ TEXT _rt0_386(SB),7,$0 ...@@ -26,12 +26,14 @@ TEXT _rt0_386(SB),7,$0
// we set up GS ourselves. // we set up GS ourselves.
MOVL initcgo(SB), AX MOVL initcgo(SB), AX
TESTL AX, AX TESTL AX, AX
JZ 4(PC) JZ needtls
PUSHL $runtime·g0(SB)
CALL AX CALL AX
POPL AX
// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows // skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
CMPL runtime·iswindows(SB), $0 CMPL runtime·iswindows(SB), $0
JEQ ok JEQ ok
needtls:
// skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases // skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
CMPL runtime·isplan9(SB), $1 CMPL runtime·isplan9(SB), $1
JEQ ok JEQ ok
...@@ -58,9 +60,15 @@ ok: ...@@ -58,9 +60,15 @@ ok:
MOVL CX, m_g0(AX) MOVL CX, m_g0(AX)
// create istack out of the OS stack // 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? LEAL (-64*1024+104)(SP), AX // TODO: 104?
MOVL AX, g_stackguard(CX) MOVL AX, g_stackguard(CX)
stackok:
MOVL SP, g_stackbase(CX) MOVL SP, g_stackbase(CX)
CALL runtime·emptyfunc(SB) // fault if stack check is wrong CALL runtime·emptyfunc(SB) // fault if stack check is wrong
// convention is D is always cleared // convention is D is always cleared
......
...@@ -17,6 +17,7 @@ TEXT _rt0_amd64(SB),7,$-8 ...@@ -17,6 +17,7 @@ TEXT _rt0_amd64(SB),7,$-8
MOVQ initcgo(SB), AX MOVQ initcgo(SB), AX
TESTQ AX, AX TESTQ AX, AX
JZ needtls JZ needtls
LEAQ runtime·g0(SB), DI
CALL AX CALL AX
CMPL runtime·iswindows(SB), $0 CMPL runtime·iswindows(SB), $0
JEQ ok JEQ ok
...@@ -44,8 +45,13 @@ ok: ...@@ -44,8 +45,13 @@ ok:
MOVQ CX, m_g0(AX) MOVQ CX, m_g0(AX)
// create istack out of the given (operating system) stack // 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 LEAQ (-8192+104)(SP), AX
MOVQ AX, g_stackguard(CX) MOVQ AX, g_stackguard(CX)
stackok:
MOVQ SP, g_stackbase(CX) MOVQ SP, g_stackbase(CX)
CLD // convention is D is always left cleared CLD // convention is D is always left cleared
......
...@@ -100,12 +100,20 @@ inittls(void) ...@@ -100,12 +100,20 @@ inittls(void)
} }
static 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(); inittls();
} }
void (*initcgo)(void) = xinitcgo; void (*initcgo)(G*) = xinitcgo;
void void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -70,12 +70,20 @@ inittls(void) ...@@ -70,12 +70,20 @@ inittls(void)
} }
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(); inittls();
} }
void (*initcgo) = xinitcgo; void (*initcgo)(G*) = xinitcgo;
void void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -8,11 +8,18 @@ ...@@ -8,11 +8,18 @@
static void* threadentry(void*); static void* threadentry(void*);
static 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 void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -8,11 +8,18 @@ ...@@ -8,11 +8,18 @@
static void* threadentry(void*); static void* threadentry(void*);
static 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 void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -9,11 +9,18 @@ ...@@ -9,11 +9,18 @@
static void *threadentry(void*); static void *threadentry(void*);
static 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 void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -3,16 +3,24 @@ ...@@ -3,16 +3,24 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include <pthread.h> #include <pthread.h>
#include <string.h> // strerror
#include "libcgo.h" #include "libcgo.h"
static void* threadentry(void*); static void* threadentry(void*);
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 void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
#include "libcgo.h" #include "libcgo.h"
static void static void
xinitcgo(void) xinitcgo(G *g)
{ {
// unimplemented
} }
void (*initcgo)(void) = xinitcgo; void (*initcgo)(G*) = xinitcgo;
void void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -13,11 +13,13 @@ static void *threadentry(void*); ...@@ -13,11 +13,13 @@ static void *threadentry(void*);
#define STACKSIZE (1*1024*1024) #define STACKSIZE (1*1024*1024)
static void static void
xinitcgo(void) xinitcgo(G *g)
{ {
int tmp;
g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
} }
void (*initcgo)(void) = xinitcgo; void (*initcgo)(G*) = xinitcgo;
void void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
...@@ -13,11 +13,13 @@ static void *threadentry(void*); ...@@ -13,11 +13,13 @@ static void *threadentry(void*);
#define STACKSIZE (2*1024*1024) #define STACKSIZE (2*1024*1024)
static void static void
xinitcgo(void) xinitcgo(G *g)
{ {
int tmp;
g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
} }
void (*initcgo)(void) = xinitcgo; void (*initcgo)(G*) = xinitcgo;
void void
libcgo_sys_thread_start(ThreadStart *ts) libcgo_sys_thread_start(ThreadStart *ts)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment