リンカーとライブラリ

実行時リンカーが検索するディレクトリ

実行時リンカーは、依存関係を探す際、デフォルトでは 1 つの場所を検索します。この場所は、32 ビットオブジェクトを処理する場合は /usr/lib、64 ビットオブジェクトを処理する場合は /usr/lib/64 です。単純なファイル名で指定された依存関係の前には、このデフォルトのディレクトリ名が付きます。このパス名を使用して、実際のファイルを見つけます。

動的実行プログラムまたは共有オブジェクトの依存関係は、ldd(1) を使用して表示できます。たとえば、ファイル /usr/bin/cat には次のような依存関係があります。


$ ldd /usr/bin/cat
        libc.so.1 =>     /usr/lib/libc.so.1
        libdl.so.1 =>    /usr/lib/libdl.so.1

ファイル /usr/bin/cat は、ファイル libc.so.1libdl.so.1 に対して依存関係を持つ、つまりこれらのファイルを必要とします。

オブジェクトに記録されている依存関係は、dump(1) を使用して調べられます。このコマンドを使用すると、ファイルの .dynamic セクションを表示して、NEEDED タグがついているエントリを探すことができます。次の例では、上記の ldd(1) の例で表示された依存関係 libdl.so.1 は、ファイル /usr/bin/cat 内に記録されていません。ldd(1) は、指定されたファイルの「すべての」依存関係を示していて、libdl.so.1 は、実際に /usr/lib/libc.so.1 の依存関係にあります。


$ dump -Lvp /usr/bin/cat
 
/usr/bin/cat:
[INDEX] Tag      Value
[1]     NEEDED   libc.so.1
.........

上記の dump(1) の例では、依存関係は単純なファイル名として表示されています。つまり、ファイル名に「/」が含まれていません。実行時リンカーが一連の規則に従ってパス名を生成するためには、単純なファイル名を使用する必要があります。「/」が組み込まれたファイル名は、そのまま使用されます。

単純なファイル名の記録は、標準的な、依存関係を記録する最も柔軟性の高いメカニズムです。リンカーに -h オプションを指定すると、依存関係内の単純な名前が記録されます。命名規約 および 共有オブジェクト名の記録 を参照してください。

依存関係は、しばしば、/usr/lib あるいは /usr/lib/64 以外に分散されます。動的実行プログラムまたは共有オブジェクトが、他のディレクトリに依存関係を配置する必要がある場合、実行時リンカーは、明示的に、このディレクトリを検索するように指示されます。

追加の検索パスは、オブジェクトごとに、オブジェクトのリンク編集中に「実行パス」を記録して指定できます。この情報の記録方法の詳細については、実行時リンカーが検索するディレクトリ を参照してください。

記録された実行パスは、dump(1) を使用して表示できます。RUNPATH タグの付いた .dynamic エントリを例示します。次の例では、proglibfoo.so.1 上に依存関係を持っています。実行時リンカーは、デフォルトの場所を調べる前に、ディレクトリ /home/me/lib/home/you/lib を検索しなければなりません。


$ dump -Lvp prog
 
prog:
[INDEX] Tag      Value
[1]     NEEDED   libfoo.so.1
[2]     NEEDED   libc.so.1
[3]     RUNPATH  /home/me/lib:/home/you/lib
.........

実行時リンカーの検索パスに追加するもう 1 つの方法は、環境変数 LD_LIBRARY_PATH を設定する方法です。この環境変数は、プロセスの始動時に 1 度分析され、コロンで区切られたディレクトリのリストに設定できます。実行時リンカーは、このリストに設定したディレクトリを、指定された実行パスまたはデフォルトのディレクトリよりも前に検索します。

これらの環境変数は、アプリケーションを強制的にローカルな依存関係に結合するといったデバッグの目的に適しています。次の例では、上記の例のファイル prog は、現在の作業ディレクトリ内で検出された libfoo.so.1 に結合されます。


$ LD_LIBRARY_PATH=. prog

環境変数 LD_LIBRARY_PATH の使用は、実行時リンカーの検索パスに影響する一時的なメカニズムとしては有用ですが、製品版ソフトウェアの場合は大きな支障があります。この環境変数を参照できる動的実行プログラムは、その検索パスを拡張させます。これにより、全体のパフォーマンスが低下する場合があります。また、環境変数の使用実行時リンカーが検索するディレクトリで説明しているとおり、LD_LIBRARY_PATH はリンカーに影響を及ぼします。

環境変数で検索パスを指定した場合、64 ビットの実行プログラムが、目的の名前と一致する 32 ビットのライブラリが格納されているパスを検索することもあり得ます。あるいは、その逆の場合もあります。このような場合、実行時リンカーは有効でない 32 ビットのライブラリを拒否し、次の検索パスを検索して、目的の名前と一致する有効な 64 ビットのライブラリを探します。一致するものが見つからない場合には、エラーメッセージが表示されます。このエラーを詳細に監視するには、LD_DEBUG 環境変数を設定して、ファイルのトークンを取り込みます。デバッギングライブラリを参照してください。


$ LD_LIBRARY_PATH=/usr/bin/64 LD_DEBUG=files /usr/bin/ls
...
00283: file=libc.so.1;  needed by /usr/bin/ls
00283: 
00283: file=/usr/lib/64/libc.so.1  rejected: ELF class mismatch: \
00283:                                  32-bit/64-bit
00283: 
00283: file=/usr/lib/libc.so.1  [ ELF ]; generating link map
00283:     dynamic:  0xef631180  base:  0xef580000  size:      0xb8000
00283:     entry:    0xef5a1240  phdr:  0xef580034  phnum:           3
00283:      lmid:           0x0
00283: 
00283: file=/usr/lib/libc.so.1;  analyzing  [ RTLD_GLOBAL  RTLD_LAZY ]
...

依存関係が配置できない場合は、ldd(1) により、オブジェクトが検出できないことが表示されます。アプリケーションを実行しようとすると、実行時リンカーから該当するエラーメッセージが表示されます。


$ ldd prog
        libfoo.so.1 =>   (file not found)
        libc.so.1 =>     /usr/lib/libc.so.1
        libdl.so.1 =>    /usr/lib/libdl.so.1
$ prog
ld.so.1: prog: fatal: libfoo.so.1: open failed: No such file or directory