替换运行时动态共享库 [英] replace a dynamic shared library in run time

查看:155
本文介绍了替换运行时动态共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要以上的程序的执行周期使用不同的动态库。综观 dlfcn.h中我认为这是可能的。我承认对动态库加载不读太多文学作品。

确定这里是我做的 -


  • 我创建了一个叫做'libdynamicTest.so.1`共享库
  • 主要的应用程序打开该solib(的dlopen ),获取函数指针(的dlsym ),运行它,然后将其关闭回( dlclose

一切都很好,直到在这里。


  • 现在,假设我被另一个libdynamicTest.so.1(约code差异)我看到分段故障更换我的libdynamicTest.so.1。而且我已经确定的 dlclose 的dlopen 前solib是后更换。

有人能解释为什么这种分割的错吗?

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

  SysTrace((打开动态库));
    处理=的dlopen(libdynamicTest.so.1,RTLD_LAZY);
    FN =的dlsym(手柄,dylib_print_msg);
    SysTrace((使用动态库));
    如果(!FN)
    {
        的printf(未知dylib_print_msg ..!\\ n);
    }
    其他
    {
        (* FN)();
    }
    RET = dlclose(句柄);
    SysTrace((关闭动态库状态= [%S],(保留== 0OK:NOK)));

P.S。我不是想修改任何现有的程序的行为,也不构成任何威胁。我在做一个可行性检查运行集成测试共享库。


修改

我试着使用gdb,以下是堆栈跟踪,故障发生时。

 计划接收信号SIGSEGV,分割过错。
从/lib64/ld-linux-x86-64.so.2 0x0000003e92408b7b在check_match.8509()
#0 0x0000003e92408b7b在check_match.8509()
   从/lib64/ld-linux-x86-64.so.2
从/lib64/ld-linux-x86-64.so.2#1 0x0000003e92409024在do_lookup_x()
#2 0x0000003e92409222在_dl_lookup_symbol_x()
   从/lib64/ld-linux-x86-64.so.2
#3 0x0000003e92908f14在do_sym()从/lib64/libc.so.6
#4 0x0000003e93001104在dlsym_doit()从/lib64/libdl.so.2
#5 0x0000003e9240ced6在_dl_catch_error()
   从/lib64/ld-linux-x86-64.so.2
从/lib64/libdl.so.2#6 0x0000003e9300150d在_dlerror_run()
从/lib64/libdl.so.2#7 0x0000003e930010ba在对dlsym()


修改

在svn签共享

code基 http://subversion.assembla.com/svn/dynamic_libso


编辑 - 添加日志LD_DEBUG =所有

  32564:绑定文件./test_agent [0]到/lib64/libc.so.6 [0]:正常符号`__libc_start_main[GLIBC_2.2.5]
     32564:
     32564:初始化程序:./test_agent
     32564:
     32564:
     32564:传送控制:./test_agent
     32564:
     32564:符号= printf的;查找文件= / test_agent [0]
     32564:符号= printf的;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:符号= printf的;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:符号= printf的;查找文件= / lib64目录/ libc.so.6的[0]
     32564:绑定文件./test_agent [0]到/lib64/libc.so.6 [0]:正常符号`printf的'[GLIBC_2.2.5]
     32564:符号=的putchar;查找文件= / test_agent [0]
     32564:符号=的putchar;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:符号=的putchar;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:符号=的putchar;查找文件= / lib64目录/ libc.so.6的[0]
     32564:绑定文件./test_agent [0]到/lib64/libc.so.6 [0]:正常符号`的putchar[GLIBC_2.2.5]
-hello.c的main():20消息:世界你好.. !!
-hello.c的main():24消息:打开动态库
     32564:符号=的dlopen;查找文件= / test_agent [0]
     32564:符号=的dlopen;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:绑定文件./test_agent [0]到/lib64/libdl.so.2 [0]:正常符号`dlopen的[GLIBC_2.2.5]
     32564:在打开文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]; direct_opencount = 1
     32564:
     32564:符号= dlerror获得;查找文件= / test_agent [0]
     32564:符号= dlerror获得;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:绑定文件./test_agent [0]到/lib64/libdl.so.2 [0]:正常符号`dlerror获得[GLIBC_2.2.5]
-hello.c的main():26消息:打开动态库句柄= [a16d9000]
     32564:符号= dlsym进行;查找文件= / test_agent [0]
     32564:符号= dlsym进行;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:绑定文件./test_agent [0]到/lib64/libdl.so.2 [0]:正常符号`dlsym进行[GLIBC_2.2.5]
     32564:符号= _dl_sym;查找文件= / test_agent [0]
     32564:符号= _dl_sym;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:符号= _dl_sym;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:符号= _dl_sym;查找文件= / lib64目录/ libc.so.6的[0]
     32564:绑定文件/lib64/libdl.so.2 [0]到/lib64/libc.so.6 [0]:正常符号`_dl_sym[GLIBC_PRIVATE]
     32564:符号= solib_print_msg;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:绑定文件/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]到/用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/libdynamicTest.so.1 [0]:正常符号`solib_print_msg
-hello.c的main():28消息:使用动态库
     32564:符号= printf的;查找文件= / test_agent [0]
     32564:符号= printf的;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:符号= printf的;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:符号= printf的;查找文件= / lib64目录/ libc.so.6的[0]
     32564:绑定文件/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]到/lib64/libc.so.6 [0]:正常符号`printf的'[ GLIBC_2.2.5]
     32564:符号=的putchar;查找文件= / test_agent [0]
     32564:符号=的putchar;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:符号=的putchar;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:符号=的putchar;查找文件= / lib64目录/ libc.so.6的[0]
     32564:绑定文件/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]到/lib64/libc.so.6 [0]:正常符号`的putchar[ GLIBC_2.2.5]
-dynamic.c solib_print_msg():9消息:尼斯.. !!
     32564:符号= dlclose;查找文件= / test_agent [0]
     32564:符号= dlclose;查找文件= / lib64目录/ libdl.so.2 [0]
     32564:绑定文件./test_agent [0]到/lib64/libdl.so.2 [0]:正常符号`dlclose[GLIBC_2.2.5]
     32564:
     32564:关闭文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1; direct_opencount = 0
-hello.c的main():40消息:关闭动态库状态= [OK]
-hello.c的main():24消息:打开动态库
     32564:在打开文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]; direct_opencount = 1
     32564:
-hello.c的main():26消息:打开动态库句柄= [0]
     32564:符号= solib_print_msg;查找文件= /用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/ libdynamicTest.so.1 [0]
     32564:绑定文件/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]到/用户/ SKM /编码/ FTEST /方法/ dynamic_library /重力/贡献/库/libdynamicTest.so.1 [0]:正常符号`solib_print_msg
-hello.c的main():28消息:使用动态库
分段故障


解决方案

从人dlclose

 函数dlclose()递减的动态引用计数
库提手。如果引用计数下降到零,
没有其他的加载库使用它的符号,那么动态库
被卸载。

我猜测你是在没有其他的加载库使用它的符号部分相抵触运行。

要调试,使用 LD_DEBUG =绑定运行程序,并查找类似的消息:

 绑定文件< some.so> [0]到libdynamicTest.so.1 [0]:正常符号`<符号GT;'

更新:

您有几个错误:


  1. 您所链接 test_agent libdynamic.so.1 直接 :结果
    CC -o test_agent -L。 ...- LDL构建/ test_agent / hello.o libdynamic.so.1

    一旦你做到了这一点,你不能再指望这个库是的曾经的卸载。


  2. 这样做:结果

    *((INT *)手柄)= 0;

    你实际上是破坏了动态加载的状态,而的会导致后续则dlsym 给你假的地址,这会导致你的 SIGSEGV 当您尝试使用它。


一旦你解决问题#2,你的程序将不再崩溃,但它仍然无法卸载该库。要的真正的获取卸载库,你也需要解决#1的问题。

如果你解决问题#1,再问题#2将不再损坏动态加载程序。它会破坏堆相反,你可以观察到平凡与Valgrind的。

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 -

  • I have created shared library called `libdynamicTest.so.1`
  • The main APP opens this solib (dlopen), gets the function pointer (dlsym), run it and then close it back (dlclose)

Everything is fine until here.

  • Now suppose I replace my libdynamicTest.so.1 by another libdynamicTest.so.1 (some code diff) I see a Segmentation fault. Further I have made sure the solib is replaced after dlclose and before dlopen.

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:

  1. 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.

  2. 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.

这篇关于替换运行时动态共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆