9

ldd特定の実行可能ファイルが使用している、または使用する予定の共有ライブラリをチェックする簡単な方法です。ただし、常に期待どおりに機能するとは限りません。たとえば、次のシェル スニペットを参照してください。これは、python バイナリへの libreadline の「依存関係」がどのように「失敗」するかを示しています。

他の多くのディストリビューションを試しましたが、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 *

だから私は2つの質問があります:

  1. 問題lddは、標準ローダーの使用を想定していることだと思いますが、Pythonは独自の特別なローダーを使用している可能性が非常に高いです(純粋ではない新しいpythonモジュールをインストールするたびに実行可能ファイルを再リンクする必要はありませんpython ですが、いくつかの c/c++/fortran コードがあります)。これは正しいです?

  2. 明らかに、実行可能ファイルが独自のローダーを使用している場合、「この実行可能ファイルがロードする可能性のあるすべてのライブラリを見つける方法」という質問に対する明確な答えはありません。それは、ローダーが何をするかに依存します。しかし、どのライブラリが 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.
4

3 に答える 3

8

Python、Perl、およびその他のインタープリター言語は、 を使用して動的にロードしますdlopen()。(これは標準ローダーを置き換えることと同じではありません。彼らはまだそれを使用しており、実際dlopen()には ELF ベースのシステムの標準ローダーへのフックです。)

ロード可能なモジュールの標準レジストリはありません。Python は独自のルールを使用して、拡張モジュールをどこからロードできるかを決定します (参照sys.path)。これには、共有オブジェクトが関連付けられているものも含まれます。Perl はさまざまなルールを使用します。Apache はさらに異なるルールなどを使用します。

質問への回答を要約すると、次のようになります。

  1. ではない正確に

  2. 番号

于 2012-04-20T20:41:40.233 に答える
1

ちなみに、質問2で私が望んでいたことを達成するための可能な方法は次のとおりです。

  • 空の chroot 環境を作成する

  • そこでPythonを再コンパイルし、不足しているものを1つずつ手動で追加します

あなたの目標に応じて、これは良い解決策であるかもしれませんし、そうでないかもしれません(そして、実際には私の目標が何であるかにはそれほど悪くないことが判明しました-質問から聞こえるかもしれませんが奇妙です)

于 2012-04-23T16:06:11.667 に答える