This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/1319] New: dlsym/RTLD_NEXT is broken when more than 1 lib has the symbol.
- From: "langlais at ilay dot org" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 9 Sep 2005 16:08:32 -0000
- Subject: [Bug libc/1319] New: dlsym/RTLD_NEXT is broken when more than 1 lib has the symbol.
- Reply-to: sourceware-bugzilla at sourceware dot org
The dlsym(RTLD_NEXT, "foo") is broken when more than one library contain the "foo".
Here are some samples :
Here are 2 little programs and 4 libraries to underline the faulty behaviour:
# the libraries:
for i in 1 2 3 4
do
cat > lib$i.c <<EOF
#include <stdio.h>
#include <dlfcn.h>
void foo() {
void (*next_foo)(void);
printf("lib$i.foo()\n");
if (next_foo = (void (*)(void)) dlsym(RTLD_NEXT, "foo")) next_foo();
}
EOF
gcc -shared -fPIC lib$i.c -o lib$i.so -D_GNU_SOURCE
done
# the test program liking libs at compile time:
cat > chain.c <<EOF
#include <dlfcn.h>
extern void foo();
int main() {
foo();
return 0;
}
EOF
gcc chain.c -o chain -L. -l1 -l2 -l3 -l4 -ldl
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./chain
#And the result :
#
# lib1.foo()
# lib2.foo()
# lib3.foo()
# lib4.foo()
#
# And now a runtime linking version:
#
cat > chain2.c <<EOF
#include <dlfcn.h>
int main() {
void *l1, *l2, *l3, *l4;
void (*bar)();
l1 = dlopen("lib1.so", RTLD_NOW | RTLD_GLOBAL);
l2 = dlopen("lib2.so", RTLD_NOW | RTLD_GLOBAL);
l3 = dlopen("lib3.so", RTLD_NOW | RTLD_GLOBAL);
l4 = dlopen("lib4.so", RTLD_NOW | RTLD_GLOBAL);
bar = (void (*)()) dlsym(RTLD_DEFAULT, "foo");
bar();
dlclose(l4);
dlclose(l3);
dlclose(l2);
dlclose(l1);
return 0;
}
EOF
gcc chain2.c -o chain2 -ldl -D_GNU_SOURCE
#
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./chain2
#
# And the result :
#
# lib1.foo()
#
On alternate plateforms (bsd/libtld, Sun/libdl) the result is :
lib1.foo()
lib2.foo()
lib3.foo()
lib4.foo()
Here is a more verbose version of chain2:
cat > chain5.c <<EOF
#include <dlfcn.h>
int main() {
void *l1, *l2, *l3, *l4;
void (*bar)();
l1 = dlopen("lib1.so", RTLD_NOW | RTLD_GLOBAL);
bar = (void (*)()) dlsym(l1, "foo");
printf("l1 is %x l1.foo is %x\n", l1, bar);
l2 = dlopen("lib2.so", RTLD_NOW | RTLD_GLOBAL);
bar = (void (*)()) dlsym(l2, "foo");
printf("l2 is %x l2.foo is %x\n", l2, bar);
l3 = dlopen("lib3.so", RTLD_NOW | RTLD_GLOBAL);
bar = (void (*)()) dlsym(l3, "foo");
printf("l3 is %x l3.foo is %x\n", l3, bar);
l4 = dlopen("lib4.so", RTLD_NOW | RTLD_GLOBAL);
bar = (void (*)()) dlsym(l4, "foo");
printf("l4 is %x l4.foo is %x\n", l4, bar);
bar = (void (*)()) dlsym(l1, "foo");
printf("l1.foo is %x \n", bar);
bar = (void (*)()) dlsym(l2, "foo");
printf("l2.foo is %x \n", bar);
bar = (void (*)()) dlsym(l3, "foo");
printf("l3.foo is %x \n", bar);
bar = (void (*)()) dlsym(l4, "foo");
printf("l4.foo is %x \n", bar);
bar = (void (*)()) dlsym(RTLD_DEFAULT, "foo");
printf("default foo is %x \n", bar);
bar();
dlclose(l4);
dlclose(l3);
dlclose(l2);
dlclose(l1);
return 0;
}
EOF
gcc chain5.c -o chain5 -ldl -D_GNU_SOURCE
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./chain5
And the result looks like this :
l1 is 804a018 l1.foo is 5556d584
l2 is 804a3b0 l2.foo is 55570584
l3 is 804a710 l3.foo is 55572584
l4 is 804aa70 l4.foo is 55574584
l1.foo is 5556d584
l2.foo is 55570584
l3.foo is 55572584
l4.foo is 55574584
default foo is 5556d584
lib1.foo()
Running the chain2 program with LD_DEBUG="files symbols" gives :
14129: symbol=dlsym; lookup in file=./chain2
14129: symbol=dlsym; lookup in file=/lib/tls/libdl.so.2
14129: symbol=_dl_sym; lookup in file=./chain2
14129: symbol=_dl_sym; lookup in file=/lib/tls/libdl.so.2
14129: symbol=_dl_sym; lookup in file=/lib/tls/libc.so.6
14129: symbol=foo; lookup in file=./chain2
14129: symbol=foo; lookup in file=/lib/tls/libdl.so.2
14129: symbol=foo; lookup in file=/lib/tls/libc.so.6
14129: symbol=foo; lookup in file=/lib/ld-linux.so.2
14129: symbol=foo; lookup in file=lib1.so
--> foo is found in lib1.so
lib1.foo()
14129: symbol=foo; lookup in file=/lib/tls/libc.so.6
14129: symbol=foo; lookup in file=/lib/ld-linux.so.2
--> Then all other lib$i.so are ignored :
14129: symbol=dlclose; lookup in file=./chain2
14129: symbol=dlclose; lookup in file=/lib/tls/libdl.so.2
14129: symbol=_dl_close; lookup in file=./chain2
14129: symbol=_dl_close; lookup in file=/lib/tls/libdl.so.2
14129: symbol=_dl_close; lookup in file=/lib/tls/libc.so.6
14129:
According to "Open Group Base Specifications Issue 6IEEE Std 1003.1, 2004
Edition" dlopen and dlsym entry, this should be a bug.
Fell free to contact me for any info.
Regards.
Yann LANGAIS.
--
Summary: dlsym/RTLD_NEXT is broken when more than 1 lib has the
symbol.
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: libc
AssignedTo: gotom at debian dot or dot jp
ReportedBy: langlais at ilay dot org
CC: glibc-bugs at sources dot redhat dot com,langlais at
ilay dot org
http://sourceware.org/bugzilla/show_bug.cgi?id=1319
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.