[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#326719: libc6-dev problem (libdl.so)



Package: libc6-dev
Version: 2.3.2

Hi.

I've encountered a problem with libdl.so.

The dlsym(RTLD_NEXT, "foo") is broken with runtime linked libraries.

Here are 2 little programs and 4 libraries to underline the faulty behavi=
our:
# 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 =3D (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=3D.:$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 =3D dlopen("lib1.so", RTLD_NOW | RTLD_GLOBAL);
         l2 =3D dlopen("lib2.so", RTLD_NOW | RTLD_GLOBAL);
         l3 =3D dlopen("lib3.so", RTLD_NOW | RTLD_GLOBAL);
         l4 =3D dlopen("lib4.so", RTLD_NOW | RTLD_GLOBAL);
         bar =3D (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=3D.:$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 =3D dlopen("lib1.so", RTLD_NOW | RTLD_GLOBAL);
         bar =3D (void (*)()) dlsym(l1, "foo");
                printf("l1 is %x l1.foo is %x\n", l1, bar);

         l2 =3D dlopen("lib2.so", RTLD_NOW | RTLD_GLOBAL);
         bar =3D (void (*)()) dlsym(l2, "foo");
                printf("l2 is %x l2.foo is %x\n", l2, bar);

         l3 =3D dlopen("lib3.so", RTLD_NOW | RTLD_GLOBAL);
         bar =3D (void (*)()) dlsym(l3, "foo");
                printf("l3 is %x l3.foo is %x\n", l3, bar);

         l4 =3D dlopen("lib4.so", RTLD_NOW | RTLD_GLOBAL);
         bar =3D (void (*)()) dlsym(l4, "foo");
                printf("l4 is %x l4.foo is %x\n", l4, bar);

         bar =3D (void (*)()) dlsym(l1, "foo");
                printf("l1.foo is %x \n", bar);
         bar =3D (void (*)()) dlsym(l2, "foo");
                printf("l2.foo is %x \n", bar);
         bar =3D (void (*)()) dlsym(l3, "foo");
                printf("l3.foo is %x \n", bar);
         bar =3D (void (*)()) dlsym(l4, "foo");
                printf("l4.foo is %x \n", bar);

         bar =3D (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=3D.:$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=3D"files symbols" gives :

     14129:     symbol=3Ddlsym;  lookup in file=3D./chain2
      14129:     symbol=3Ddlsym;  lookup in file=3D/lib/tls/libdl.so.2
      14129:     symbol=3D_dl_sym;  lookup in file=3D./chain2
      14129:     symbol=3D_dl_sym;  lookup in file=3D/lib/tls/libdl.so.2
      14129:     symbol=3D_dl_sym;  lookup in file=3D/lib/tls/libc.so.6
      14129:     symbol=3Dfoo;  lookup in file=3D./chain2
      14129:     symbol=3Dfoo;  lookup in file=3D/lib/tls/libdl.so.2
      14129:     symbol=3Dfoo;  lookup in file=3D/lib/tls/libc.so.6
      14129:     symbol=3Dfoo;  lookup in file=3D/lib/ld-linux.so.2
      14129:     symbol=3Dfoo;  lookup in file=3Dlib1.so

--> foo is found in lib1.so

lib1.foo()
      14129:     symbol=3Dfoo;  lookup in file=3D/lib/tls/libc.so.6
      14129:     symbol=3Dfoo;  lookup in file=3D/lib/ld-linux.so.2

--> Then all other lib$i.so are ignored :

      14129:     symbol=3Ddlclose;  lookup in file=3D./chain2
      14129:     symbol=3Ddlclose;  lookup in file=3D/lib/tls/libdl.so.2
      14129:     symbol=3D_dl_close;  lookup in file=3D./chain2
      14129:     symbol=3D_dl_close;  lookup in file=3D/lib/tls/libdl.so.=
2
      14129:     symbol=3D_dl_close;  lookup in file=3D/lib/tls/libc.so.6
      14129:


Apparently, the problem is not new and may not be specific to debian.




Regards,

Yann LANGLAIS
http://ilay.org
langlais@ilay.org
--
    I r i s
L i l a
é   A n g e l a
o   Y a n n
    . o r g




Reply to: