This is the mail archive of the
libc-alpha@cygnus.com
mailing list for the glibc project.
Bug in dlsym() (scope problem(?) & RTLD_NEXT problem)
- To: libc-alpha@cygnus.com
- Subject: Bug in dlsym() (scope problem(?) & RTLD_NEXT problem)
- From: Kars de Jong <jongk@cs.utwente.nl>
- Date: Wed, 7 Oct 1998 15:36:10 +0200
>Submitter-Id: net
>Originator: Kars de Jong
>Organization: none
>Confidential: no
>Synopsis: A bug in dlsym() causes it to lookup the wrong symbol.
>Severity: serious
>Priority: high
>Category: libc
>Class: sw-bug
>Release: libc-2.0.96
>Environment:
Host type: m68k-unknown-linux-gnu
System: Linux rincewind 2.1.120 #9 Wed Sep 30 23:48:01 CEST 1998 m68k unknown
Architecture: m68k
Addons: crypt linuxthreads
Build CFLAGS: -pipe -O2 -m68060
Build CC: egcs
Compiler version: egcs-2.91.57 19980901 (egcs-1.1 release)
Kernel headers: 2.1.120
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: no
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio
>Description:
When using dlsym() to lookup a symbol in a shared object from (at
least) another shared object it fails to give the correct symbol when
the symbol is defined in the calling shared object as well. Example:
The JDK 1.1.5 opens libc.so.6 from a shared object (libjava.so). Then
it wants to store the symbols of a number of functions to make them
thread-safe with their green_threads package. To this end it opens
libc.so.6, then does a dlsym(libc6handle, "write"). This however
returns a pointer to the write function as defined in libjava.so!
With previous releases, using dlsym(RTLD_NEXT, "write") doesn't work
either. It also returns the symbol from the calling shared object
instead of the C-library (as is what happens under Solaris).
>How-To-Repeat:
file bing.c:
#include <dlfcn.h>
#include <stdio.h>
#define HOW_DLOPEN 0
#define HOW_RTLD_NEXT 1
int write(int fd, const void *buf, size_t size) {
return 0;
}
void setup_table(int how) {
void *sym = NULL;
if (how == HOW_DLOPEN) {
void *handle = NULL;
handle = dlopen("libc.so.6", RTLD_LAZY);
if (!handle)
return;
sym = dlsym(handle, "write");
fprintf(stderr, "DLOPEN: %p should not equal %p...\n",
write, sym);
dlcose(handle);
} else /* how == HOW_RTLD_NEXT */ {
sym = dlsym(RTLD_NEXT, "write");
fprintf(stderr, "RTLD_NEXT: %p should not equal "
"%p...\n", write, sym);
}
}
file dltest.c:
extern void setup_table(int how);
#define HOW_DLOPEN 0
#define HOW_RTLD_NEXT 1
int main() {
setup_table(HOW_DLOPEN);
setup_table(HOW_RTLD_NEXT);
return 0;
}
Compile & run:
gcc -fPIC -O -g -shared -o bing.so bing.c
gcc -O -g -o dltest dltest.c bing.so -ldl -Wl,-rpath -Wl,.
./dltest
The 2 printed pointers should not be the same. They are, however, for
both methods. I tested this on a i586-pc-linux-gnu platform too.
Fix:
Nope, sorry. It might be due to the fact that write is a weak symbol
in the C library. It would be best to use RTLD_NEXT anyway, to
avoid version problems. But since that's broken as well...
--
------------------------------------------------------------------------------
Kars de Jong Signaalkamp rules the waves! Turrican@Discworld
--------======]**-----| jongk@cs.utwente.nl |-----**[======---------