リンカーとライブラリ

共有オブジェクトの依存性

実行時リンカーがプログラムのメモリーセグメントを作成するとき、依存性は、プログラムのサービスを提供するためにどの共有オブジェクトが必要であるかを示します。参照された共有オブジェクトとそれが依存するものを繰り返し結合することによって、実行時リンカーは完全なプロセスイメージを生成します。


注 –

共有オブジェクトが依存性リストにおいて複数回参照されるときでも、実行時リンカーはこの共有オブジェクトをプロセスに 1 回だけ結合します。


共有オブジェクトの依存関係の検索

動的実行可能プログラムのリンク中に、1 つまたは複数の共有オブジェクトが明示的に参照されます。これらのオブジェクトは、依存関係として動的実行可能プログラム内に記録されます。

実行時リンカーはこの依存情報を使用して、関連オブジェクトを検索して読み込みます。これらの依存関係は、実行プログラムのリンク編集中に参照された順番で処理されます。

動的実行可能プログラムの依存関係がすべて読み込まれると、各依存関係も読み込まれた順番に検査され、追加の依存関係が配置されます。この処理は、すべての依存関係の配置と読み込みが完了するまで続きます。この技術の結果、すべての依存関係が幅優先順になります。

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

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

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


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

ファイル /usr/bin/cat には依存関係があり、ファイル libc.so.1libm.so.2必要としています

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


$ elfdump -d /usr/bin/cat
 
Dynamic Section:  .dynamic:
     index  tag                value
       [0]  NEEDED            0x211               libc.so.1
       ...

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

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

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

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

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


$ elfdump -d prog | egrep "NEEDED|RUNPATH"
       [1]  NEEDED            0x4ce               libfoo.so.1
       [3]  NEEDED            0x4f6               libc.so.1
      [21]  RUNPATH           0x210e              /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 環境変数を設定して、files のトークンを取り込みます。「デバッギングライブラリ」を参照してください。


$ LD_LIBRARY_PATH=/lib/64 LD_DEBUG=files /usr/bin/ls
...
00283: file=libc.so.1;  needed by /usr/bin/ls
00283: 
00283: file=/lib/64/libc.so.1  rejected: ELF class mismatch: 32–bit/64–bit
00283: 
00283: file=/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=/lib/libc.so.1;  analyzing  [ RTLD_GLOBAL  RTLD_LAZY ]
...

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


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

デフォルトの検索パスの設定

実行時リンカーが使用するデフォルトの検索パスは、32 ビットアプリケーションの場合、/lib/usr/lib です。64 ビットアプリケーションの場合、デフォルト検索パスは /lib/64/usr/lib/64 です。このような検索パスを管理するには、crle(1) ユーティリティーで作成する実行時構成ファイルを使用します。このファイルは、正しい「実行パス」で作成されなかったアプリケーションについて検索パスを設定する場合に便利です。

構成ファイルが作成されるデフォルトの場所は、32 ビットアプリケーションの場合は /var/ld/ld.config、64 ビットアプリケーションの場合は /var/ld/64/ld.config です。このファイルは、システム上の、それぞれのタイプのアプリケーションすべてに影響します。構成ファイルはこれ以外の場所にも作成でき、実行時リンカーの LD_CONFIG 環境変数を使用してこれらのファイルを選択できます。後者の方法は、構成ファイルをデフォルトの場所にインストールする前にテストする場合に便利です。

動的ストリングトークン

実行時リンカーは、さまざまな動的ストリングトークンを展開できます。このようなトークンは、フィルタ、「実行パス」、および依存関係の定義に利用できます。