ldd是检查给定可执行文件正在或将要使用的共享库的一种很好的简单方法。然而,它并不总是像预期的那样工作。例如,请参见下面的shell代码段,它演示了如何“失败”在python二进制文件中找到li威行“依赖项”。
我尝试过许多其他发行版,但我正在从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查看ldd对默认安装的python (从官方存储库)所做的操作。
$ 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
$什么都没发现。现在,我从交互用法中了解到,这个二进制文件确实具有realine功能,所以不要试图查看它的来源。
$ 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对啰!这里是读行!
但是,只有当库有效加载时,这种技术才能工作,因此,例如,直到python进程没有运行类似于/usr/lib64/libtcl8.4.so的东西时,它才会找到from Tkinter import *。
所以我有两个问题:
ldd的问题在于它假设使用标准加载器,而python很可能使用自己的特殊加载器(这样,每次安装一个不是纯python但有一些c/c++/fortran代码的新python模块时,就不必重新链接可执行文件)。如果一个可执行文件正在使用自己的加载程序,那么“如何找到这个可执行文件可能加载的所有可能库”这个问题没有明显的答案:这取决于加载程序的操作。但是有什么方法可以找出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.发布于 2012-04-20 20:41:40
Python、Perl和其他解释语言使用dlopen()动态加载东西。(这与替换标准加载程序不同;他们仍在使用标准加载程序,实际上,dlopen()是基于ELF系统的标准加载程序的挂钩。)
没有可加载模块的标准注册表。Python使用自己的规则来确定可以从哪里加载扩展模块(查看sys.path),包括那些具有关联共享对象的扩展模块。Perl使用不同的规则。Apache仍然使用不同的规则,等等。
因此,总结一下你的问题的答案:
exactly
非
发布于 2012-04-23 16:06:11
作为附带说明,实现我在问题2中所希望的目标的一种可能办法是:
environment
python,手动添加任何丢失的东西,一个接一个的。
取决于您的目标,这可能是一个好的解决方案,也可能不是一个好的解决方案(实际上,对于我的目标来说,这并不是太糟糕--尽管从问题中听起来可能很奇怪)。
发布于 2019-12-17 23:57:53
使用ldd -v也可以转储库依赖项。下面是一个示例:
ave-ssh-test:tmp# ldd -v /sbin/coop.bin
linux-vdso.so.1 => (0x00007fffd45f0000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x0000730cace67000)
.
.
.
Version information:
/lib64/libstdc++.so.6:
ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
libm.so.6 (GLIBC_2.2.5) => /lib64/libm.so.6
libgcc_s.so.1 (GCC_4.2.0) => /lib64/libgcc_s.so.1
libgcc_s.so.1 (GCC_3.3) => /lib64/libgcc_s.so.1
libgcc_s.so.1 (GCC_3.0) => /lib64/libgcc_s.so.1
libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
libc.so.6 (GLIBC_2.3.2) => /lib64/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6https://stackoverflow.com/questions/10253170
复制相似问题