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 @@
void
callback(void *f)
{
// use some stack space
volatile char data[64*1024];
data[0] = 0;
goCallback(f);
data[sizeof(data)-1] = 0;
}
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
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