在运行时replacedynamic共享库

我需要在程序的执行周期中使用不同的dynamic库。 看着dlfcn.h我以为这是可能的。 我承认没有阅读大量有关dynamic库加载的文献。

好的,这是我做的 –

  • 我创build了名为`libdynamicTest.so.1`的共享库
  • 主APP打开这个solib( dlopen ),获取函数指针( dlsym ),运行它然后closures它( dlclose

一切都很好,直到这里。

  • 现在假设我将libdynamicTest.so.1replace为另一个libdynamicTest.so.1(一些代码差异),我看到一个分段错误。 此外,我已经确定solib在dlclose之后和dlopen之前被replace。

有人可以解释为什么这个分割错误?

我注意到即使我删除了libdynamicTest.so.1程序仍然执行,安静的怪。

  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"))); 

PS我不是想修改任何现有程序的行为,也不会造成任何威胁。 我正在做一个可行性检查作为共享库运行集成testing。


编辑

我试着用gdb,下面是堆栈跟踪,发生故障的时候。

 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 

编辑

代码库共享在svn结帐http://subversion.assembla.com/svn/dynamic_libso


编辑: – 添加日志LD_DEBUG =全部

 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 

Solutions Collecting From Web of "在运行时replacedynamic共享库"

从“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. 

我猜你正在碰到“没有其他加载的库在其中使用符号”部分。

要进行调试,请使用LD_DEBUG=bindings运行程序,然后查找如下消息:

 binding file <some.so> [0] to libdynamicTest.so.1 [0]: normal symbol `<symbol>' 

更新:

你有几个错误:

  1. 直接test_agentlibdynamic.so.1链接起来:
    cc -o test_agent -L. ...-ldl build/test_agent/hello.o libdynamic.so.1

    一旦你这样做,你不能再期望这个库被卸载。

  2. 通过做这个:

    *((int *)handle) = 0;

    你实际上正在破坏动态加载器的状态,并导致随后的dlsym给你伪造的地址,当你尝试使用它的时候会导致你的SIGSEGV

一旦你解决了问题#2,你的程序将不再崩溃,尽管它仍然不会卸载库。 要真正让图书馆卸载,还需要修复问题#1。

如果你先解决问题#1,那么问题#2将不再破坏动态加载器。 它会腐坏堆,你可以用Valgrind轻松地观察。

根据man 8 ld.so

 BUGS Currently ld.so has no means of unloading and searching for com‐ patible or newer version of libraries. 

我不是100%肯定这是相关的,但它听起来像是可能的。