检查非默认加载器的共享库

ldd是一个很好的简单的方法来检查一个给定的可执行文件是或将要使用的共享库。 然而,它并不总是按预期工作。 例如,请参阅下面的shell代码片段,演示如何将libreadline“dependency”创build为python二进制文件

我已经尝试了很多其他的发行版,但我从Tikanga复制

 $ lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch Distributor ID: RedHatEnterpriseServer Description: Red Hat Enterprise Linux Server release 5.6 (Tikanga) Release: 5.6 Codename: Tikanga 

看看默认安装的python (从官方仓库) ldd做什么。

 $ which python /usr/bin/python $ ldd `which python` libpython2.4.so.1.0 => /usr/lib64/libpython2.4.so.1.0 (0x00000030e6200000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030e0e00000) libdl.so.2 => /lib64/libdl.so.2 (0x00000030e0a00000) libutil.so.1 => /lib64/libutil.so.1 (0x00000030ee800000) libm.so.6 => /lib64/libm.so.6 (0x00000030e0600000) libc.so.6 => /lib64/libc.so.6 (0x00000030e0200000) /lib64/ld-linux-x86-64.so.2 (0x00000030dfe00000) $ ldd `which python` | grep readline $ 

readline没有任何发现。 现在我从交互式的使用中知道这个二进制文件有真正的function,所以我们不要试图看看它来自哪里。

 $ python & [1] 21003 $ Python 2.4.3 (#1, Dec 10 2010, 17:24:35) [GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2 Type "help", "copyright", "credits" or "license" for more information. [1]+ Stopped python 

在后台启动了一个交互式Python会话(pid 21003)

 $ lsof -p 21003 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME python 21003 ddvento cwd DIR 0,33 16384 164304 /glade/home/ddvento/loader-test python 21003 ddvento rtd DIR 8,3 4096 2 / python 21003 ddvento txt REG 8,3 8304 6813419 /usr/bin/python python 21003 ddvento mem REG 8,3 143600 8699326 /lib64/ld-2.5.so python 21003 ddvento mem REG 8,3 1722304 8699327 /lib64/libc-2.5.so python 21003 ddvento mem REG 8,3 615136 8699490 /lib64/libm-2.5.so python 21003 ddvento mem REG 8,3 23360 8699458 /lib64/libdl-2.5.so python 21003 ddvento mem REG 8,3 145824 8699445 /lib64/libpthread-2.5.so python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 python 21003 ddvento mem REG 8,3 15840 8699446 /lib64/libtermcap.so.2.0.8 python 21003 ddvento mem REG 8,3 1244792 6833317 /usr/lib64/libpython2.4.so.1.0 python 21003 ddvento mem REG 8,3 18152 8699626 /lib64/libutil-2.5.so python 21003 ddvento mem REG 8,3 56446448 6832889 /usr/lib/locale/locale-archive python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so python 21003 ddvento mem REG 8,3 25464 6901074 /usr/lib64/gconv/gconv-modules.cache python 21003 ddvento 0u CHR 136,1 3 /dev/pts/1 python 21003 ddvento 1u CHR 136,1 3 /dev/pts/1 python 21003 ddvento 2u CHR 136,1 3 /dev/pts/1 $ lsof -p 21003 | grep readline python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so 

答对了! 这里是readline!

然而,这种技术只有在库被有效地加载时才起作用,所以例如它不会find/usr/lib64/libtcl8.4.so直到python进程不能运行类似from Tkinter import *

所以我有两个问题:

  1. 我相信ldd的问题在于它假定使用标准加载器,而python很可能使用它自己的特殊加载器(这样你就不必在每次安装新的python模块时不要重新链接可执行文件纯Python,但有一些C / C ++ / Fortran代码)。 它是否正确?

  2. 显然,如果一个可执行文件使用自己的加载器,那么对于“如何find这个可执行文件可能加载的所有可能的库”这个问题没有明显的答案:这取决于加载器的function。 但是有没有办法找出哪些库可能被python加载?

PS:与1有关。如果你在这个问题上登陆,你应该已经知道下面的内容,但是如果你不这样做:看看如何简单地把ldd输出搞乱(只是部分搞乱了它有点困难):

 $ cat hello.c #include <stdio.h> int main() { printf("Hello world.\n"); return 0; } $ gcc -static hello.c -o loader $ gcc -Wl,--dynamic-linker,./loader hello.c -o hello $ ./hello Hello world. $ ldd ./hello Hello world. 

Solutions Collecting From Web of "检查非默认加载器的共享库"

Python,Perl和其他解释语言使用dlopen()动态地加载东西。 (这与替换标准加载器不同,它们仍在使用它,事实上dlopen()是基于ELF的系统上的标准加载器的钩子。

没有可加载模块的标准注册表。 Python使用自己的规则来确定扩展模块可以从哪里加载(查看sys.path ),包括那些有关联的共享对象。 Perl使用不同的规则。 Apache仍然使用不同的规则等

所以总结一下你的问题的答案:

  1. 不完全是

  2. 没有

作为一个侧面说明,一个可能的方式来完成我想问的问题2将是:

  • 创建一个空的chrooted环境

  • 在那里重新编译python,手动添加一个一个地丢失的东西

根据你的目标,这可能或可能不是一个好的解决方案(事实上,对于我的目标来说不是太糟糕 – 这听起来很奇怪)