I need to use different dynamic library over a execution cycle of a program. Looking at dlfcn.h
I thought this was possible. I confess of not reading much literature on dynamic library loading.
OK here is what I do -
Everything is fine until here.
Can someone explain why this segmentation fault ?
I noticed even if I delete libdynamicTest.so.1 the program still executes, quiet strange.
SysTrace(("opening dynamic library"));
handle = dlopen("libdynamicTest.so.1",RTLD_LAZY);
fn = dlsym (handle,"dylib_print_msg");
SysTrace(("Using dynamic library"));
if(!fn)
{
printf("unknown dylib_print_msg..!!\n");
}
else
{
(*fn)();
}
ret = dlclose(handle);
SysTrace(("closed dynamic library status = [%s]", (ret==0?"OK":"NOK")));
P.S. I am not trying to modify the behavior of any existing program, nor pose any threat. I was doing a feasibility check to run integration tests as shared libraries.
edit
I tried with gdb, following is the stack trace, when the fault occurred.
Program received signal SIGSEGV, Segmentation fault.
0x0000003e92408b7b in check_match.8509 () from /lib64/ld-linux-x86-64.so.2
#0 0x0000003e92408b7b in check_match.8509 ()
from /lib64/ld-linux-x86-64.so.2
#1 0x0000003e92409024 in do_lookup_x () from /lib64/ld-linux-x86-64.so.2
#2 0x0000003e92409222 in _dl_lookup_symbol_x ()
from /lib64/ld-linux-x86-64.so.2
#3 0x0000003e92908f14 in do_sym () from /lib64/libc.so.6
#4 0x0000003e93001104 in dlsym_doit () from /lib64/libdl.so.2
#5 0x0000003e9240ced6 in _dl_catch_error ()
from /lib64/ld-linux-x86-64.so.2
#6 0x0000003e9300150d in _dlerror_run () from /lib64/libdl.so.2
#7 0x0000003e930010ba in dlsym () from /lib64/libdl.so.2
edit
code base shared at svn checkout http://subversion.assembla.com/svn/dynamic_libso
edit :- added logs LD_DEBUG=all
32564: binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `__libc_start_main' [GLIBC_2.2.5]
32564:
32564: initialize program: ./test_agent
32564:
32564:
32564: transferring control: ./test_agent
32564:
32564: symbol=printf; lookup in file=./test_agent [0]
32564: symbol=printf; lookup in file=/lib64/libdl.so.2 [0]
32564: symbol=printf; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: symbol=printf; lookup in file=/lib64/libc.so.6 [0]
32564: binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `printf' [GLIBC_2.2.5]
32564: symbol=putchar; lookup in file=./test_agent [0]
32564: symbol=putchar; lookup in file=/lib64/libdl.so.2 [0]
32564: symbol=putchar; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: symbol=putchar; lookup in file=/lib64/libc.so.6 [0]
32564: binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `putchar' [GLIBC_2.2.5]
-hello.c main():20 Msg : hello world ..!!
-hello.c main():24 Msg : opening dynamic library
32564: symbol=dlopen; lookup in file=./test_agent [0]
32564: symbol=dlopen; lookup in file=/lib64/libdl.so.2 [0]
32564: binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlopen' [GLIBC_2.2.5]
32564: opening file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]; direct_opencount=1
32564:
32564: symbol=dlerror; lookup in file=./test_agent [0]
32564: symbol=dlerror; lookup in file=/lib64/libdl.so.2 [0]
32564: binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlerror' [GLIBC_2.2.5]
-hello.c main():26 Msg : Opened dynamic library handle = [a16d9000]
32564: symbol=dlsym; lookup in file=./test_agent [0]
32564: symbol=dlsym; lookup in file=/lib64/libdl.so.2 [0]
32564: binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlsym' [GLIBC_2.2.5]
32564: symbol=_dl_sym; lookup in file=./test_agent [0]
32564: symbol=_dl_sym; lookup in file=/lib64/libdl.so.2 [0]
32564: symbol=_dl_sym; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: symbol=_dl_sym; lookup in file=/lib64/libc.so.6 [0]
32564: binding file /lib64/libdl.so.2 [0] to /lib64/libc.so.6 [0]: normal symbol `_dl_sym' [GLIBC_PRIVATE]
32564: symbol=solib_print_msg; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]: normal symbol `solib_print_msg'
-hello.c main():28 Msg : Using dynamic library
32564: symbol=printf; lookup in file=./test_agent [0]
32564: symbol=printf; lookup in file=/lib64/libdl.so.2 [0]
32564: symbol=printf; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: symbol=printf; lookup in file=/lib64/libc.so.6 [0]
32564: binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /lib64/libc.so.6 [0]: normal symbol `printf' [GLIBC_2.2.5]
32564: symbol=putchar; lookup in file=./test_agent [0]
32564: symbol=putchar; lookup in file=/lib64/libdl.so.2 [0]
32564: symbol=putchar; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: symbol=putchar; lookup in file=/lib64/libc.so.6 [0]
32564: binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /lib64/libc.so.6 [0]: normal symbol `putchar' [GLIBC_2.2.5]
-dynamic.c solib_print_msg():9 Msg : nice nice..!!
32564: symbol=dlclose; lookup in file=./test_agent [0]
32564: symbol=dlclose; lookup in file=/lib64/libdl.so.2 [0]
32564: binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlclose' [GLIBC_2.2.5]
32564:
32564: closing file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1; direct_opencount=0
-hello.c main():40 Msg : closed dynamic library status = [OK]
-hello.c main():24 Msg : opening dynamic library
32564: opening file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]; direct_opencount=1
32564:
-hello.c main():26 Msg : Opened dynamic library handle = [0]
32564: symbol=solib_print_msg; lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
32564: binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]: normal symbol `solib_print_msg'
-hello.c main():28 Msg : Using dynamic library
Segmentation fault
From "man dlclose":
The function dlclose() decrements the reference count on the dynamic
library handle handle. If the reference count drops to zero and
no other loaded libraries use symbols in it, then the dynamic library
is unloaded.
I am guessing that you are running afoul of the "no other loaded libraries use symbols in it" part.
To debug, run your program with LD_DEBUG=bindings
, and look for messages like:
binding file <some.so> [0] to libdynamicTest.so.1 [0]: normal symbol `<symbol>'
Update:
You have several bugs:
You are linking test_agent
against libdynamic.so.1
directly:cc -o test_agent -L. ...-ldl build/test_agent/hello.o libdynamic.so.1
Once you've done this, you can no longer expect this library to be ever unloaded.
By doing this:
*((int *)handle) = 0;
you are actually corrupting the state of the dynamic loader, and that causes subsequent dlsym
to give you bogus address, which causes your SIGSEGV
when you try to use it.
Once you fix problem #2, your program will no longer crash, though it will still not unload the library. To actually get the library to unload, you need to also fix problem #1.
If you fix problem #1 first, then problem #2 will no longer corrupt the dynamic loader. It will corrupt heap instead, and you can trivially observe that with Valgrind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With