On 05/03/2013 12:11 PM, Paul Pluzhnikov wrote: > On Fri, May 3, 2013 at 8:11 AM, Simon Richter <s...@debian.org> wrote: > >> I'm writing a small preload library to trace pthread_* calls ... >> In order to find the original function, I use dlsym(RTLD_NEXT, ...) ... > >> In any case, I am wondering if it is actually possible to redirect the >> pthread_* functions in this way, or if a different approach is required. > > In general: no. You can't expect dlsym() to not call any pthread_* > functions. Even if this happens to work today for some versions of > glibc on Linux, there is absolutely no guarantee that it will continue > to work tomorrow.
In practice dlsym() won't call any pthread_* functions until libpthread.so is loaded. Once loaded all the internal locking functions will redirect to the real locking functions, but in the shared case they redirect through a global structure of pointers in the dynamic loader. This assignment happens in nptl/nptl-ini.c (__pthread_initialize_minimal_internal): ~~~ /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock, keep the lock count from the ld.so implementation. */ GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock; GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock; ~~~ In the non-shared case we use weak symbols to detect libpthread.a was linked, but still only call through the internal name, see nptl/sysdeps/pthread/bits/libc-lockP.h: ~~~ # define __rtld_lock_lock_recursive(NAME) \ __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) # define __rtld_lock_unlock_recursive(NAME) \ __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) ~~~ Thus unless you are the *actual* libpthread.so you won't be able to intercept the dynamic loader's internal calls to libpthread.so. You can however intercept libpthread.so calls from outside of libc.so. Perhaps this is the reason it works on Linux and not other OSs? Cheers, Carlos.