|
From: Tatulea, D. <dra...@in...> - 2012-10-26 12:19:53
|
Hi,
I've been investigating an x86 android bug for quite a while now:
spawning threads via pthread generates undefined values in
__thread_entry. See below for details:
*** The Error ***
==1271== Memcheck, a memory error detector
==1271== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==1271== Using Valgrind-3.9.0.SVN and LibVEX; rerun with -h for copyright info
==1271== Command: /data/hg01_all_ok
==1271==
==1271== (action at startup) vgdb me ...
==1271==
==1271== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==1271== /path/to/gdb /data/hg01_all_ok
==1271== and then give GDB the following command
==1271== target remote |
/data/local/Inst/lib/valgrind/../../bin/vgdb --pid=1271
==1271== --pid is optional if only one valgrind process is running
==1271==
==1271== Thread 2:
==1271== Conditional jump or move depends on uninitialised value(s)
==1271== at 0x4017AAA: pthread_mutex_lock (pthread.c:1043)
==1271== Uninitialised value was created by a stack allocation
==1271== at 0x4016BB1: __thread_entry (pthread.c:203)
==1271==
==1271== (action on error) vgdb me ...
*** The Code ***
Follow the BUG comments below.
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
int mtype, tid, new_lock_type, shared;
/* BUG:
This is where it happens, mutex is 0x100fff00 (it's v bits defined) and
it's location on the stack is 0x100ffec4 (v bits undefined).
See bellow for caller.
*/
if (__unlikely(mutex == NULL))
return EINVAL;
mtype = (mutex->value & MUTEX_TYPE_MASK);
shared = (mutex->value & MUTEX_SHARED_MASK);
/* Handle normal case first */
..................
/*
* This trampoline is called from the assembly clone() function
*/
void __thread_entry(int (*func)(void*), void *arg, void **tls)
{
int retValue;
pthread_internal_t * thrInfo;
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before it starts doing anything.
//
// This also provides the memory barrier needed to ensure that all memory
// accesses previously made by the creating thread are visible to us.
pthread_mutex_t *start_mutex = (pthread_mutex_t *)&tls[TLS_SLOT_SELF];
/* BUG:
start_mutex is 0x100fff00, located at 0x100ffee0 (v bits
undefined). The tls var
stack location is undefined.
*/
pthread_mutex_lock(start_mutex);
pthread_mutex_destroy(start_mutex);
thrInfo = (pthread_internal_t *) tls[TLS_SLOT_THREAD_ID];
__init_tls( tls, thrInfo );
pthread_exit( (void*)func(arg) );
}
The whole code can be found here [1].
*** Questions & Comments ***
- The addr tls is fetched via i686.get_pc_thunk.bx (which just does a
mov (%esp),%ebx && ret).
- This is not happening on ARM, as PhilippeW has mentioned.
- For ARM, all the stack is defined, which is not the case on x86
which looks rather random (the local variables are marked as defined
but the fn parameters are undefined).
So, how can the stack be marked as undefined? I'm at a point where I
could really use some clues to move on with fixing this bug.
[1] - http://androidxref.com/4.1.1/xref/bionic/libc/bionic/pthread.c#199
Thanks,
Dragos
|