This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Re: Wrapping versioned glibc symbol
- From: Tomash Brechko <tomash dot brechko at gmail dot com>
- To: libc-help at sourceware dot org
- Date: Fri, 24 Apr 2009 17:25:50 +0400
- Subject: Re: Wrapping versioned glibc symbol
- Bcc: Tomash Brechko <tomash_brechko>
- References: <20090424100543.GA4045@tbrechko.office.ocslab.com>
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