Wrapping versioned glibc symbol
Tomash Brechko
tomash.brechko@gmail.com
Fri Apr 24 13:26:00 GMT 2009
On Fri, Apr 24, 2009 at 14:05:43 +0400, Tomash Brechko wrote:
> So, is there a canonical way to wrap versioned functions? Perhaps I
> approach the problem from the wrong side...
I'm still curious learning how to solve the problem "statically"
(i.e. at compile time), if possible at all. However my colleague
reminded me that I can just use dlsym(). First I tried
__pthread_cond_signal = dlsym(RTLD_NEXT, "pthread_cond_signal");
This seemed to work, but in gdb I noticed that __pthread_cond_signal
is bound to pthread_cond_signal@GLIBC_2.0, not
pthread_cond_signal@@GLIBC_2.3.2 ! For glibc 2.8 the program below
outputs
$ ./test
pthread_cond_signal:
./libc_bug(pthread_cond_signal+0x0)[0x8048524]
RTLD_DEFAULT:
./libc_bug(pthread_cond_signal+0x0)[0x8048524]
RTLD_NEXT:
/lib/libpthread.so.0(pthread_cond_signal+0x0)[0xd19950]
dlopen:
/lib/libpthread.so.0(pthread_cond_signal+0x0)[0xd196a0]
$ nm /lib/libpthread.so.0 | grep '\bpthread_cond_signal\b'
00d196a0 T pthread_cond_signal@@GLIBC_2.3.2
00d19950 T pthread_cond_signal@GLIBC_2.0
As you can see, RTLD_DEFAULT binds to my own definition, but RTLD_NEXT
binds to @GLIBC_2.0, skipping @@GLIBC_2.3.2. I think this contradicts
man dlopen, that says that RTLD_NEXT "allows one to provide a wrapper
around a function in another shared library". The only working
solution left is to explicitly dlopen("/lib/libpthread.so.0", ...).
/*
gcc -pthread test.c -o test -ldl
./test
nm /lib/libpthread.so.0 | grep '\bpthread_cond_signal\b'
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
int
pthread_cond_signal(pthread_cond_t *cond)
{
return 0;
}
int
main()
{
void *libpthread;
void *addr;
fputs("pthread_cond_signal:\n", stdout);
addr = pthread_cond_signal;
backtrace_symbols_fd(&addr, 1, 1);
fputs("RTLD_DEFAULT:\n", stdout);
addr = dlsym(RTLD_DEFAULT, "pthread_cond_signal");
backtrace_symbols_fd(&addr, 1, 1);
fputs("RTLD_NEXT:\n", stdout);
addr = dlsym(RTLD_NEXT, "pthread_cond_signal");
backtrace_symbols_fd(&addr, 1, 1);
fputs("dlopen:\n", stdout);
libpthread = dlopen("/lib/libpthread.so.0", RTLD_LAZY);
addr = dlsym(libpthread, "pthread_cond_signal");
backtrace_symbols_fd(&addr, 1, 1);
return 0;
}
--
Tomash Brechko
More information about the Libc-help
mailing list