mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-27 11:52:03 +00:00
Tweaks to make libthread tell Valgrind about its stack limits,
so that Valgrind can detect stack overflow for me.
This commit is contained in:
parent
cdd61ab0ae
commit
a3785ca2cc
7 changed files with 60 additions and 8 deletions
|
@ -1,8 +1,23 @@
|
||||||
#include "threadimpl.h"
|
#include "threadimpl.h"
|
||||||
|
/*
|
||||||
|
* To use this you need some patches to Valgrind that
|
||||||
|
* let it help out with detecting stack overflow.
|
||||||
|
*/
|
||||||
|
#define USEVALGRIND 0
|
||||||
|
#ifdef USEVALGRIND
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
launcher386(void (*f)(void *arg), void *arg)
|
launcher386(void (*f)(void *arg), void *arg)
|
||||||
{
|
{
|
||||||
|
Proc *p;
|
||||||
|
Thread *t;
|
||||||
|
|
||||||
|
p = _threadgetproc();
|
||||||
|
t = p->thread;
|
||||||
|
_threadstacklimit(t->stk);
|
||||||
|
|
||||||
(*f)(arg);
|
(*f)(arg);
|
||||||
threadexits(nil);
|
threadexits(nil);
|
||||||
}
|
}
|
||||||
|
@ -19,3 +34,24 @@ _threadinitstack(Thread *t, void (*f)(void*), void *arg)
|
||||||
t->sched.sp = (ulong)tos - 8; /* old PC and new PC */
|
t->sched.sp = (ulong)tos - 8; /* old PC and new PC */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadinswitch(int enter)
|
||||||
|
{
|
||||||
|
USED(enter);
|
||||||
|
#ifdef USEVALGRIND
|
||||||
|
if(enter)
|
||||||
|
VALGRIND_SET_STACK_LIMIT(0, 0, 1);
|
||||||
|
else
|
||||||
|
VALGRIND_SET_STACK_LIMIT(0, 0, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadstacklimit(void *addr)
|
||||||
|
{
|
||||||
|
USED(addr);
|
||||||
|
|
||||||
|
#ifdef USEVALGRIND
|
||||||
|
VALGRIND_SET_STACK_LIMIT(1, addr, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ _setlabel:
|
||||||
.type _gotolabel,@function
|
.type _gotolabel,@function
|
||||||
|
|
||||||
_gotolabel:
|
_gotolabel:
|
||||||
|
pushl $1
|
||||||
|
call _threadinswitch
|
||||||
|
popl %eax
|
||||||
movl 4(%esp), %edx
|
movl 4(%esp), %edx
|
||||||
movl 0(%edx), %ecx
|
movl 0(%edx), %ecx
|
||||||
movl 4(%edx), %ebx
|
movl 4(%edx), %ebx
|
||||||
|
@ -24,9 +27,12 @@ _gotolabel:
|
||||||
movl 12(%edx), %ebp
|
movl 12(%edx), %ebp
|
||||||
movl 16(%edx), %esi
|
movl 16(%edx), %esi
|
||||||
movl 20(%edx), %edi
|
movl 20(%edx), %edi
|
||||||
|
movl %ecx, 0(%esp)
|
||||||
|
pushl $0
|
||||||
|
call _threadinswitch
|
||||||
|
popl %eax
|
||||||
xorl %eax, %eax
|
xorl %eax, %eax
|
||||||
incl %eax
|
incl %eax
|
||||||
movl %ecx, 0(%esp)
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ static void
|
||||||
channelsize(Channel *c, int sz)
|
channelsize(Channel *c, int sz)
|
||||||
{
|
{
|
||||||
if(c->e != sz){
|
if(c->e != sz){
|
||||||
fprint(2, "expected channel with elements of size %d, got size %d",
|
fprint(2, "expected channel with elements of size %d, got size %d\n",
|
||||||
sz, c->e);
|
sz, c->e);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,3 +53,6 @@ trend: trend.$O $PLAN9/lib/$LIB
|
||||||
|
|
||||||
CLEANFILES=$CLEANFILES tprimes texec
|
CLEANFILES=$CLEANFILES tprimes texec
|
||||||
|
|
||||||
|
asm-Linux-386.$O: asm-FreeBSD-386.s
|
||||||
|
asm-NetBSD-386.$O: asm-FreeBSD-386.s
|
||||||
|
asm-OpenBSD-386.$O: asm-FreeBSD-386.s
|
||||||
|
|
|
@ -166,14 +166,15 @@ Resched:
|
||||||
p = _threadgetproc();
|
p = _threadgetproc();
|
||||||
//fprint(2, "p %p\n", p);
|
//fprint(2, "p %p\n", p);
|
||||||
if((t = p->thread) != nil){
|
if((t = p->thread) != nil){
|
||||||
if((ulong)&p < (ulong)t->stk){ /* stack overflow */
|
if((ulong)&p < (ulong)t->stk+512){ /* stack overflow waiting to happen */
|
||||||
fprint(2, "stack overflow %lux %lux\n", (ulong)&p, (ulong)t->stk);
|
fprint(2, "stack overflow: stack at %lux, limit at %lux\n", (ulong)&p, (ulong)t->stk);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
// _threaddebug(DBGSCHED, "pausing, state=%s set %p goto %p",
|
// _threaddebug(DBGSCHED, "pausing, state=%s set %p goto %p",
|
||||||
// psstate(t->state), &t->sched, &p->sched);
|
// psstate(t->state), &t->sched, &p->sched);
|
||||||
if(_setlabel(&t->sched)==0)
|
if(_setlabel(&t->sched)==0)
|
||||||
_gotolabel(&p->sched);
|
_gotolabel(&p->sched);
|
||||||
|
_threadstacklimit(t->stk);
|
||||||
return;
|
return;
|
||||||
}else{
|
}else{
|
||||||
t = runthread(p);
|
t = runthread(p);
|
||||||
|
|
|
@ -219,4 +219,4 @@ extern int _threadgetpid(void);
|
||||||
extern void _threadmemset(void*, int, int);
|
extern void _threadmemset(void*, int, int);
|
||||||
extern void _threaddebugmemset(void*, int, int);
|
extern void _threaddebugmemset(void*, int, int);
|
||||||
extern int _threadprocs;
|
extern int _threadprocs;
|
||||||
|
extern void _threadstacklimit(void*);
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
#include <lib9.h>
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STACK = 8192
|
||||||
|
};
|
||||||
|
|
||||||
int quiet;
|
int quiet;
|
||||||
int goal;
|
int goal;
|
||||||
int buffer;
|
int buffer;
|
||||||
|
@ -19,7 +25,7 @@ primethread(void *arg)
|
||||||
if(!quiet)
|
if(!quiet)
|
||||||
print("%d\n", p);
|
print("%d\n", p);
|
||||||
nc = chancreate(sizeof(ulong), buffer);
|
nc = chancreate(sizeof(ulong), buffer);
|
||||||
(*fn)(primethread, nc, 8192);
|
(*fn)(primethread, nc, STACK);
|
||||||
for(;;){
|
for(;;){
|
||||||
i = recvul(c);
|
i = recvul(c);
|
||||||
if(i%p)
|
if(i%p)
|
||||||
|
@ -56,7 +62,7 @@ threadmain(int argc, char **argv)
|
||||||
goal = 100;
|
goal = 100;
|
||||||
|
|
||||||
c = chancreate(sizeof(ulong), buffer);
|
c = chancreate(sizeof(ulong), buffer);
|
||||||
(*fn)(primethread, c, 8192);
|
(*fn)(primethread, c, STACK);
|
||||||
for(i=2;; i++)
|
for(i=2;; i++)
|
||||||
sendul(c, i);
|
sendul(c, i);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue