检查共享库中的非默认加载器 [英] checking shared libraries for non default loaders
问题描述
ldd
是检查给定可执行文件正在使用或将要使用的共享库的简单好方法.但是,它并不总是能按预期工作.例如,请参见下面的shell片段,该片段演示了如何失败"将libreadline"dependency"发现到python二进制文件中
ldd
is a good simple way to check for shared libraries a given executable is or will be using. However it does not always work as expected. For example, see the following shell snippet that demonstrates how it "fails" to found the libreadline "dependency" into the python binary
我尝试了许多其他发行版,但我是从Tikanga复制
I've tried many other distributions, but I'm copying from 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
(来自官方存储库)的作用.
See what ldd
does on the default installed python
(from official repositories).
$ 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的信息.现在,我确实从交互式用法中知道该二进制文件确实具有实时功能,所以不要尝试查看它的来源.
Nothing found about readline. Now I do know from interactive usage that this binary does have realine functionality, so let't try to see where it's coming from.
$ 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)
Started an interactive python session in background (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!
Bingo! Here it is readline!
但是,此技术仅在有效加载库后才有效,例如,直到python进程未运行from Tkinter import *
However, this technique works only when the library is effectively loaded, so for example it does not find /usr/lib64/libtcl8.4.so
until the python process does not run something like from Tkinter import *
所以我有两个问题:
-
我相信
ldd
的问题在于它假设使用了标准加载程序,而python很可能正在使用其自己的特殊加载程序(因此您不必每次都重新链接可执行文件安装一个新的python模块,该模块不是纯python,而是具有一些c/c ++/fortran代码).这是正确的吗?
I believe the problem with
ldd
is that it assumes the usage of the standard loader, whereas very likely python is using its own special loader (so that you don't have to relink the executable every time you install a new python module that is not pure python but has some c/c++/fortran code). Is this correct?
很显然,如果一个可执行文件正在使用其自己的加载程序,则如何找到该可执行文件可能加载的所有可能的库"这一问题没有明显的答案:这取决于加载程序的工作.但是有没有办法找出python可以加载哪些库?
Clearly, if an executable is using its own loader, there is no obvious answer to the question "how to find all the possible libraries this executable may load": it depends on what the loader does. But is there a way to find out what libraries may be loaded by python?
PS:与1相关.如果您着眼于这个问题,您应该已经知道以下内容,但是如果不了解,您应该:完全弄乱ldd
输出(将其仅部分弄乱是很简单的)是多么简单.有点困难):
PS: related to 1. If you are landing on this question you should already know the following, but if don't you should: see how simple is to completely mess up ldd
output (messing it up only partially is a little harder):
$ 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.
推荐答案
Python,Perl和其他解释型语言确实使用dlopen()
动态加载内容. (这与替换标准加载器不同;他们仍在使用它,实际上dlopen()
是对基于ELF的系统上标准加载器的一个钩子.)
Python, Perl, and other interpreted languages do load things dynamically using dlopen()
. (This is not the same thing as replacing the standard loader; they are still using that, and in fact dlopen()
is a hook into the standard loader on ELF-based systems.)
没有可加载模块的标准注册表. Python使用自己的规则来确定可从何处加载扩展模块(请参见sys.path
),包括那些具有关联共享对象的模块. Perl使用不同的规则. Apache使用的规则仍然不同,等等.
There is no standard registry for loadable modules. Python uses its own rules to determine where extension modules can be loaded from (look at sys.path
), including those which have associated shared objects. Perl uses different rules. Apache uses still different rules, etc.
因此,总结一下您的问题的答案:
So to summarize the answers to your questions:
-
不完全
not exactly
否
这篇关于检查共享库中的非默认加载器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!