From: Julian Seward Date: Sat, 13 Apr 2002 00:08:51 +0000 (+0000) Subject: Write return address for threads in assembly so we can reliably X-Git-Tag: svn/VALGRIND_1_0_3~388 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac45cc3e3890754f6b8c2e0f2a266709f4f67dc1;p=thirdparty%2Fvalgrind.git Write return address for threads in assembly so we can reliably grab their return values. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@58 --- diff --git a/coregrind/vg_constants.h b/coregrind/vg_constants.h index 9fb6a23781..b4e359b383 100644 --- a/coregrind/vg_constants.h +++ b/coregrind/vg_constants.h @@ -103,7 +103,8 @@ /* Assembly code stubs make these requests ... */ #define VG_USERREQ__SIGNAL_RETURNS 0x4001 -#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4002 +#define VG_USERREQ__PTHREAD_RETURNS 0x4002 +#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4003 #endif /* ndef __VG_INCLUDE_H */ diff --git a/coregrind/vg_helpers.S b/coregrind/vg_helpers.S index 4d1f8c2629..e0afa6c081 100644 --- a/coregrind/vg_helpers.S +++ b/coregrind/vg_helpers.S @@ -68,6 +68,37 @@ signalreturn_bogusRA_panic_msg: .text + +.global VG_(pthreadreturn_bogusRA) +VG_(pthreadreturn_bogusRA): + subl $20, %esp # allocate arg block + movl %esp, %edx # %edx == &_zzq_args[0] + movl $VG_USERREQ__PTHREAD_RETURNS, 0(%edx) # request + movl %eax, 4(%edx) # arg1 == thread return value + movl $0, 8(%edx) # arg2 + movl $0, 12(%edx) # arg3 + movl $0, 16(%edx) # arg4 + movl %edx, %eax + # and now the magic sequence itself: + roll $29, %eax + roll $3, %eax + rorl $27, %eax + rorl $5, %eax + roll $13, %eax + roll $19, %eax + # should never get here + pushl $pthreadreturn_bogusRA_panic_msg + call VG_(panic) + +.data +pthreadreturn_bogusRA_panic_msg: +.ascii "vg_pthreadreturn_bogusRA: VG_USERREQ__PTHREAD_RETURNS was missed" +.byte 0 +.text + + + + /* ------------------ REAL CPU HELPERS ------------------ */ /* The rest of this lot run on the real CPU. */ diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 0833cae833..52706e0395 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -400,19 +400,19 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__PTHREAD_CREATE 0x3001 -#define VG_USERREQ__PTHREAD_CREATE_BOGUSRA 0x3002 -#define VG_USERREQ__PTHREAD_JOIN 0x3003 -#define VG_USERREQ__PTHREAD_GET_THREADID 0x3004 -#define VG_USERREQ__PTHREAD_MUTEX_INIT 0x3005 -#define VG_USERREQ__PTHREAD_MUTEX_LOCK 0x3006 -#define VG_USERREQ__PTHREAD_MUTEX_UNLOCK 0x3007 -#define VG_USERREQ__PTHREAD_MUTEX_DESTROY 0x3008 -#define VG_USERREQ__PTHREAD_CANCEL 0x3009 +#define VG_USERREQ__PTHREAD_JOIN 0x3002 +#define VG_USERREQ__PTHREAD_GET_THREADID 0x3003 +#define VG_USERREQ__PTHREAD_MUTEX_INIT 0x3004 +#define VG_USERREQ__PTHREAD_MUTEX_LOCK 0x3005 +#define VG_USERREQ__PTHREAD_MUTEX_UNLOCK 0x3006 +#define VG_USERREQ__PTHREAD_MUTEX_DESTROY 0x3007 +#define VG_USERREQ__PTHREAD_CANCEL 0x3008 /* In vg_constants.h: #define VG_USERREQ__SIGNAL_RETURNS 0x4001 -#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4002 +#define VG_USERREQ__PTHREAD_RETURNS 0x4002 +#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4003 */ @@ -1520,8 +1520,9 @@ extern void VG_(helper_value_check2_fail); extern void VG_(helper_value_check1_fail); extern void VG_(helper_value_check0_fail); -/* NOT A FUNCTION; a bogus RETURN ADDRESS. */ +/* NOT FUNCTIONS; these are bogus RETURN ADDRESS. */ extern void VG_(signalreturn_bogusRA)( void ); +extern void VG_(pthreadreturn_bogusRA)( void ); /* --------------------------------------------------------------------- diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index e748db1709..ff1697c4d2 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -47,9 +47,6 @@ anyone at all! - signals interrupting read/write and nanosleep, and take notice of SA_RESTART or not -- return bogus RA: %EAX trashed, so pthread_joiner gets nonsense - exit codes - - when a thread is done mark its stack as noaccess - make signal return and .fini call be detected via request mechanism @@ -1182,20 +1179,6 @@ VgSchedReturnCode VG_(scheduler) ( void ) typedef unsigned long int pthread_t; */ -/* RUNS ON SIMD CPU! - This is the return address that pthread_create uses. -*/ -static -void do_pthread_create_bogusRA ( void ) -{ - /* Tell the scheduler that this thread has returned. */ - Int res; - VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, - VG_USERREQ__PTHREAD_CREATE_BOGUSRA, - 0, 0, 0, 0); - VG_(panic)("do_pthread_create_bogusRA: shouldn't be still alive!"); -} - static void do_pthread_cancel ( ThreadId tid_canceller, @@ -1211,17 +1194,18 @@ void do_pthread_cancel ( ThreadId tid_canceller, print_sched_event(tid_cancellee, msg_buf); } vg_threads[tid_cancellee].m_eax = (UInt)PTHREAD_CANCELED; - vg_threads[tid_cancellee].m_eip = (UInt)&do_pthread_create_bogusRA; + vg_threads[tid_cancellee].m_eip = (UInt)&VG_(pthreadreturn_bogusRA); vg_threads[tid_cancellee].status = VgTs_Runnable; } /* Thread tid is exiting, by returning from the function it was - created with. The main complication here is to resume any thread - waiting to join with this one. */ + created with. Or possibly due to pthread_exit or cancellation. + The main complication here is to resume any thread waiting to join + with this one. */ static -void do_pthread_create_exit_by_returning ( ThreadId tid ) +void handle_pthread_return ( ThreadId tid, void* retval ) { ThreadId jnr; /* joiner, the thread calling pthread_join. */ UInt* jnr_args; @@ -1233,7 +1217,7 @@ void do_pthread_create_exit_by_returning ( ThreadId tid ) vg_assert(tid >= 0 && tid < VG_N_THREADS); vg_assert(vg_threads[tid].status != VgTs_Empty); - vg_threads[tid].retval = (void*)vg_threads[tid].m_eax; + vg_threads[tid].retval = retval; if (vg_threads[tid].joiner == VG_INVALID_THREADID) { /* No one has yet done a join on me */ @@ -1401,7 +1385,7 @@ void do_pthread_create ( ThreadId parent_tid, /* push (magical) return address */ vg_threads[tid].m_esp -= 4; - * (UInt*)(vg_threads[tid].m_esp) = (UInt)do_pthread_create_bogusRA; + * (UInt*)(vg_threads[tid].m_esp) = (UInt)VG_(pthreadreturn_bogusRA); if (VG_(clo_instrument)) VGM_(make_readable)( vg_threads[tid].m_esp, 2 * 4 ); @@ -1687,8 +1671,8 @@ void do_nontrivial_clientreq ( ThreadId tid ) (void*)arg[4] ); break; - case VG_USERREQ__PTHREAD_CREATE_BOGUSRA: - do_pthread_create_exit_by_returning( tid ); + case VG_USERREQ__PTHREAD_RETURNS: + handle_pthread_return( tid, (void*)arg[1] ); break; case VG_USERREQ__PTHREAD_JOIN: diff --git a/vg_constants.h b/vg_constants.h index 9fb6a23781..b4e359b383 100644 --- a/vg_constants.h +++ b/vg_constants.h @@ -103,7 +103,8 @@ /* Assembly code stubs make these requests ... */ #define VG_USERREQ__SIGNAL_RETURNS 0x4001 -#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4002 +#define VG_USERREQ__PTHREAD_RETURNS 0x4002 +#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4003 #endif /* ndef __VG_INCLUDE_H */ diff --git a/vg_helpers.S b/vg_helpers.S index 4d1f8c2629..e0afa6c081 100644 --- a/vg_helpers.S +++ b/vg_helpers.S @@ -68,6 +68,37 @@ signalreturn_bogusRA_panic_msg: .text + +.global VG_(pthreadreturn_bogusRA) +VG_(pthreadreturn_bogusRA): + subl $20, %esp # allocate arg block + movl %esp, %edx # %edx == &_zzq_args[0] + movl $VG_USERREQ__PTHREAD_RETURNS, 0(%edx) # request + movl %eax, 4(%edx) # arg1 == thread return value + movl $0, 8(%edx) # arg2 + movl $0, 12(%edx) # arg3 + movl $0, 16(%edx) # arg4 + movl %edx, %eax + # and now the magic sequence itself: + roll $29, %eax + roll $3, %eax + rorl $27, %eax + rorl $5, %eax + roll $13, %eax + roll $19, %eax + # should never get here + pushl $pthreadreturn_bogusRA_panic_msg + call VG_(panic) + +.data +pthreadreturn_bogusRA_panic_msg: +.ascii "vg_pthreadreturn_bogusRA: VG_USERREQ__PTHREAD_RETURNS was missed" +.byte 0 +.text + + + + /* ------------------ REAL CPU HELPERS ------------------ */ /* The rest of this lot run on the real CPU. */ diff --git a/vg_include.h b/vg_include.h index 0833cae833..52706e0395 100644 --- a/vg_include.h +++ b/vg_include.h @@ -400,19 +400,19 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__PTHREAD_CREATE 0x3001 -#define VG_USERREQ__PTHREAD_CREATE_BOGUSRA 0x3002 -#define VG_USERREQ__PTHREAD_JOIN 0x3003 -#define VG_USERREQ__PTHREAD_GET_THREADID 0x3004 -#define VG_USERREQ__PTHREAD_MUTEX_INIT 0x3005 -#define VG_USERREQ__PTHREAD_MUTEX_LOCK 0x3006 -#define VG_USERREQ__PTHREAD_MUTEX_UNLOCK 0x3007 -#define VG_USERREQ__PTHREAD_MUTEX_DESTROY 0x3008 -#define VG_USERREQ__PTHREAD_CANCEL 0x3009 +#define VG_USERREQ__PTHREAD_JOIN 0x3002 +#define VG_USERREQ__PTHREAD_GET_THREADID 0x3003 +#define VG_USERREQ__PTHREAD_MUTEX_INIT 0x3004 +#define VG_USERREQ__PTHREAD_MUTEX_LOCK 0x3005 +#define VG_USERREQ__PTHREAD_MUTEX_UNLOCK 0x3006 +#define VG_USERREQ__PTHREAD_MUTEX_DESTROY 0x3007 +#define VG_USERREQ__PTHREAD_CANCEL 0x3008 /* In vg_constants.h: #define VG_USERREQ__SIGNAL_RETURNS 0x4001 -#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4002 +#define VG_USERREQ__PTHREAD_RETURNS 0x4002 +#define VG_USERREQ__SHUTDOWN_VALGRIND 0x4003 */ @@ -1520,8 +1520,9 @@ extern void VG_(helper_value_check2_fail); extern void VG_(helper_value_check1_fail); extern void VG_(helper_value_check0_fail); -/* NOT A FUNCTION; a bogus RETURN ADDRESS. */ +/* NOT FUNCTIONS; these are bogus RETURN ADDRESS. */ extern void VG_(signalreturn_bogusRA)( void ); +extern void VG_(pthreadreturn_bogusRA)( void ); /* --------------------------------------------------------------------- diff --git a/vg_scheduler.c b/vg_scheduler.c index e748db1709..ff1697c4d2 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -47,9 +47,6 @@ anyone at all! - signals interrupting read/write and nanosleep, and take notice of SA_RESTART or not -- return bogus RA: %EAX trashed, so pthread_joiner gets nonsense - exit codes - - when a thread is done mark its stack as noaccess - make signal return and .fini call be detected via request mechanism @@ -1182,20 +1179,6 @@ VgSchedReturnCode VG_(scheduler) ( void ) typedef unsigned long int pthread_t; */ -/* RUNS ON SIMD CPU! - This is the return address that pthread_create uses. -*/ -static -void do_pthread_create_bogusRA ( void ) -{ - /* Tell the scheduler that this thread has returned. */ - Int res; - VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, - VG_USERREQ__PTHREAD_CREATE_BOGUSRA, - 0, 0, 0, 0); - VG_(panic)("do_pthread_create_bogusRA: shouldn't be still alive!"); -} - static void do_pthread_cancel ( ThreadId tid_canceller, @@ -1211,17 +1194,18 @@ void do_pthread_cancel ( ThreadId tid_canceller, print_sched_event(tid_cancellee, msg_buf); } vg_threads[tid_cancellee].m_eax = (UInt)PTHREAD_CANCELED; - vg_threads[tid_cancellee].m_eip = (UInt)&do_pthread_create_bogusRA; + vg_threads[tid_cancellee].m_eip = (UInt)&VG_(pthreadreturn_bogusRA); vg_threads[tid_cancellee].status = VgTs_Runnable; } /* Thread tid is exiting, by returning from the function it was - created with. The main complication here is to resume any thread - waiting to join with this one. */ + created with. Or possibly due to pthread_exit or cancellation. + The main complication here is to resume any thread waiting to join + with this one. */ static -void do_pthread_create_exit_by_returning ( ThreadId tid ) +void handle_pthread_return ( ThreadId tid, void* retval ) { ThreadId jnr; /* joiner, the thread calling pthread_join. */ UInt* jnr_args; @@ -1233,7 +1217,7 @@ void do_pthread_create_exit_by_returning ( ThreadId tid ) vg_assert(tid >= 0 && tid < VG_N_THREADS); vg_assert(vg_threads[tid].status != VgTs_Empty); - vg_threads[tid].retval = (void*)vg_threads[tid].m_eax; + vg_threads[tid].retval = retval; if (vg_threads[tid].joiner == VG_INVALID_THREADID) { /* No one has yet done a join on me */ @@ -1401,7 +1385,7 @@ void do_pthread_create ( ThreadId parent_tid, /* push (magical) return address */ vg_threads[tid].m_esp -= 4; - * (UInt*)(vg_threads[tid].m_esp) = (UInt)do_pthread_create_bogusRA; + * (UInt*)(vg_threads[tid].m_esp) = (UInt)VG_(pthreadreturn_bogusRA); if (VG_(clo_instrument)) VGM_(make_readable)( vg_threads[tid].m_esp, 2 * 4 ); @@ -1687,8 +1671,8 @@ void do_nontrivial_clientreq ( ThreadId tid ) (void*)arg[4] ); break; - case VG_USERREQ__PTHREAD_CREATE_BOGUSRA: - do_pthread_create_exit_by_returning( tid ); + case VG_USERREQ__PTHREAD_RETURNS: + handle_pthread_return( tid, (void*)arg[1] ); break; case VG_USERREQ__PTHREAD_JOIN: