ldd
- это хороший простой способ проверить наличие общих библиотек, которые использует или будет использовать данный исполняемый файл. Однако это не всегда работает так, как ожидалось. Например, см. Следующий фрагмент кода, который демонстрирует, как он "не удается" найти зависимость "libreadline" в двоичном файле 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
Посмотрите, что делает 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
$
Ничего не найдено о readline. Теперь я знаю из интерактивного использования, что этот бинарный файл имеет реальную функциональность, поэтому не будем пытаться увидеть, откуда он.
$ 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!
Однако этот метод работает только тогда, когда библиотека эффективно загружена, поэтому, например, она не находит /usr/lib64/libtcl8.4.so
, пока процесс python не запускает что-то вроде from Tkinter import *
У меня есть два вопроса:
-
Я считаю, что проблема с
ldd
заключается в том, что он предполагает использование стандартного загрузчика, тогда как очень вероятно, что python использует свой собственный специальный загрузчик (так что вам не нужно повторно запускать исполняемый файл каждый раз, когда вы установите новый модуль python, который не является чистым python, но имеет некоторый код c/С++/fortran). Правильно ли это? -
Очевидно, что если исполняемый файл использует свой собственный загрузчик, нет очевидного ответа на вопрос "как найти все возможные библиотеки, которые может загружать этот исполняемый файл": это зависит от того, что делает загрузчик. Но есть ли способ узнать, какие библиотеки могут быть загружены с помощью 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.