ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

c – 依赖地狱:linux .so插件动态加载

2019-06-23 14:39:11  阅读:413  来源: 互联网

标签:c-2 linux dependencies shared-libraries dynamic-loading


我使用linuxbrew创建了一个使用独立构建树构建的共享库,由于依赖性冲突,它无法加载到父应用程序中.我正在使用一个单独的应用程序,它在启动后使用Qt5 QLibrary类动态加载库.

我的库是libv_repExtPluginSkeleton.so.它和父应用程序都依赖于glibc和libstdc.所有主应用程序的依赖项都在/usr/lib中,而我所有库的依赖项都在〜/ .linuxbrew / lib中.

当父应用程序加载.so失败时,我使用LD_DEBUG = all“$dirname / $appname”调试失败,并在输出中找到以下错误报告:

  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  dynamically loaded by libQt5Core.so.5 [0]
  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  generating link map
  2610:   dynamic: 0x00007fd063cff570  base: 0x00007fd063ae7000   size: 0x000000000021a6a8
  2610:     entry: 0x00007fd063af1150  phdr: 0x00007fd063ae7040  phnum:                  5
  2610: 
  2610: checking for version `GCC_3.0' in file /lib/x86_64-linux-gnu/libgcc_s.so.1 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBC_2.14' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `CXXABI_1.3' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBCXX_3.4.9' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBCXX_3.4.21' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: error: version lookup error: version `GLIBCXX_3.4.21' not found (required by /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so) (fatal)
  2610: 
  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  destroying link map

正如您所看到的,当我的库加载时,似乎已加载的glibc版本在/usr/lib中,但我的库需要在〜/ .linuxbrew / lib中加载版本.

QLibrary用于加载插件,如下所示:

plug=new CPlugin(filename,pluginName);
int loadRes=plug->load();

我在The Inside Story on Shared Libraries and Dynamic Loading中读到“动态加载的模块与底层应用程序完全分离”,如果可以使其正常工作,我想重新配置加载过程来解决问题.

以下是ldd找到的依赖项列表,它说明了不同位置的依赖项重叠:

+ ldd /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so
    linux-vdso.so.1 (0x00007fffc17af000)
    libstdc++.so.6 => /home/hbr/.linuxbrew/lib/libstdc++.so.6 (0x00007ff5b9a32000)
    libm.so.6 => /home/hbr/.linuxbrew/lib/libm.so.6 (0x00007ff5b9742000)
    libgcc_s.so.1 => /home/hbr/.linuxbrew/lib/libgcc_s.so.1 (0x00007ff5b9531000)
    libc.so.6 => /home/hbr/.linuxbrew/lib/libc.so.6 (0x00007ff5b91b9000)
    /home/hbr/.linuxbrew/Cellar/glibc/2.19/lib64/ld-linux-x86-64.so.2 (0x00007ff5b9f81000)
+ ldd /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/vrep
    linux-vdso.so.1 =>  (0x00007ffc333f9000)
    liblua5.1.so (0x00007fc10e763000)
    libQt5Core.so.5 (0x00007fc10df28000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc10dd0a000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc10da
  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  dynamically loaded by libQt5Core.so.5 [0]
  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  generating link map
  2610:   dynamic: 0x00007fd063cff570  base: 0x00007fd063ae7000   size: 0x000000000021a6a8
  2610:     entry: 0x00007fd063af1150  phdr: 0x00007fd063ae7040  phnum:                  5
  2610: 
  2610: checking for version `GCC_3.0' in file /lib/x86_64-linux-gnu/libgcc_s.so.1 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBC_2.14' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `CXXABI_1.3' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBCXX_3.4.9' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: checking for version `GLIBCXX_3.4.21' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
  2610: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: error: version lookup error: version `GLIBCXX_3.4.21' not found (required by /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so) (fatal)
  2610: 
  2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0];  destroying link map

)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc10d7f0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc10d42b000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc10d125000)
libicui18n.so.54 (0x00007fc10ccb7000)
libicuuc.so.54 (0x00007fc10c909000)
libicudata.so.54 (0x00007fc10aedf000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc10acdb000)
libgthread-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0 (0x00007fc10aad9000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc10a8d1000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fc10a5c9000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc10e66d000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fc10a38b000)
+ LD_DEBUG=all /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/vrep

解决方法:

How can I resolve this version conflict so that my library loads correctly?

这对libc或libstdc等基本的低级库不起作用.这些库管理全局对象的数量(内存管理,线程,环境,语言环境等),并且在同一地址空间中具有多个不同版本的库是灾难的处方.更重要的是,不保证不同libstdc版本的STL类在内存中具有相同的二进制布局.应用程序内的std :: string可能与库中的std :: string不同.从/向插件传递一个可能会导致难以调试的崩溃. (你为libstdc获得的错误消息部分是对这种情况的保护.)这导致了一个问题(即使你静态链接libstdc)你的插件的功能将无法接受或返回STL类作为参数/返回值 – 只有基本的C类型.

此外,通过动态加载,另一个障碍是Linux / UNIX链接器使用具有其符号的扁平线性列表的扁平线性列表库.并且库由内部soname标识,而不是文件名.链接器将所寻找的符号绑定到第一个,通过线性搜索通过库列表及其符号找到.稍后加载的库将从已经为应用程序本身加载的库中获得大部分符号.您的插件引用的库可能甚至都没有被查看.

总的来说,您的选择非常有限:

>静态链接.将插件与所需库的静态变体相链接.但是,如果您需要覆盖libc或libstdc,那么这不起作用.
>服务器/客户端方法.插件库是一个瘦包装器,只启动服务器进程,然后通过某种RPC机制将所有从应用程序到插件的调用重定向到此服务器应用程序.这是解决库版本冲突的唯一可靠方法.由于与库不同,应用程序可以更好地控制动态链接器(rpath,或者在最坏的情况下使用LD_PRELOAD).

通常,正如其他人之前所说的那样,您应该始终使用随操作系统安装的libc和libstdc,并根据需要为不同的OS变体发布不同的版本.

标签:c-2,linux,dependencies,shared-libraries,dynamic-loading
来源: https://codeday.me/bug/20190623/1271751.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有