リンカーとライブラリ

共有オブジェクトの依存関係の配置

通常、動的実行プログラムのリンク編集中に、1 つまたは複数の共有オブジェクトが明示的に参照されます。これらのオブジェクトは、依存関係として動的実行プログラム内に記録されます (詳細については、「共有オブジェクトの処理」を参照)。

実行時リンカーは、まず最初にこの依存情報を配置し、これを使用して関連オブジェクトの配置および対応付けを行います。これらの依存関係は、実行プログラムのリンク編集中に参照された順番で処理されます。

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

実行時リンカーによって検索されるディレクトリ

デフォルトでは、実行時リンカーが、依存関係の検出場所として認識しているのは、32 ビットの依存関係の場合は /usr/lib、64 ビット SPARC の依存関係の場合は /usr/lib/sparcv9 という標準的なディレクトリだけです。単純なファイル名で指定された依存関係には、このディレクトリ名が接頭辞として付き、この接頭辞が付いたパス名は、実際のファイルを配置する場合に使用されます。

動的実行プログラムまたは共有オブジェクトの実際の依存関係は、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 が必要です。

ファイル内に実際に記録された依存関係は、ファイルの .dynamic セクションと NEEDED タグの付いたエントリの参照を表示する dump(1) コマンドを使用して検査できます。次に例を示します。


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

上記の ldd(1) の例で表示された依存関係 libdl.so.1 は、ファイル /usr/bin/cat 内に記録されないことに注意してください。これは、つまり ldd(1) が、指定されたファイルのすべての依存関係を示していて、libdl.so.1 は、実際に /usr/lib/libc.so.1 の依存関係であるためです。

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

単純なファイル名の記録は、標準的な、依存関係を記録する最も柔軟性の高いメカニズムで、依存関係内の単純な名前を記録する、リンカーの -h オプションを使用して実行されます (このトピックの詳細については、「命名規約」「共有オブジェクト名の記録」を参照)。

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

追加の検索パスを実行時リンカーに指示する場合は、動的実行プログラムまたは共有オブジェクトのリンク編集中に、「実行パス」を記録する方法をお勧めします (この情報の記録方法の詳細については、「実行時リンカーが検索するディレクトリ」を参照)。

実行パスの記録は、dump(1) を使用して表示し、RPATH タグの付いたエントリを参照できます。次に例を示します。


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

ここでは、proglibfoo.so.1 上に依存関係を持っていて、実行時リンカーのデフォルトロケーション /usr/lib を調べる前に、ディレクトリ /home/me/lib/home/you/lib を検索するように要求します。

実行時リンカーの検索パスに追加するもう 1 つの方法は、環境変数 LD_LIBRARY_PATH を設定する方法です。この環境変数は、プロセスの始動時に 1 度分析され、コロンで区切られたディレクトリのリストに設定できます。実行時リンカーは、このリストに設定したディレクトリを、指定された実行パスまたはデフォルトのディレクトリよりも前に検索します。64 ビット SPARC の実行プログラムは、環境変数 LD_LIBRARY_PATH_64 を使用し、この変数によって、アクティブな LD_LIBRARY_PATH 設定は上書きされます。

これらの環境変数は、アプリケーションを強制的に局所的な依存関係に結合するといったデバッグの目的に適しています。次に例を示します。


$ LD_LIBRARY_PATH=. prog

ここで、上記の例のファイル prog は、現在の作業ディレクトリ内で検出された libfoo.so.1 に結合されます。

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

64 ビット SPARC の実行プログラムが、検出する名前と一致する 32 ビットのライブラリを組み込んだ検索パスを持つように、またはその逆の環境を継承できます。このような場合、動的リンカーは一致しない 32 ビットライブラリを拒否し、有効な 64 ビットと一致するライブラリを検出して、検索パスの処理を続けます。一致するものが見つからない場合には、エラーメッセージが表示されます。このエラーは、LD_DEBUG 環境変数 (「デバッギングエイド」を参照) を設定してファイルを組み込むことによって、詳細に監視できます。


$ LD_LIBRARY_PATH=/usr/bin/sparcv9 LD_DEBUG=files /usr/bin/ls
...
00283: file=libc.so.1;  needed by /usr/bin/ls
00283: 
00283: file=/usr/lib/sparcv9/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

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

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

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

動的ストリングトークン

実行時リンカーは、実行パス (DT_RPATH)、フィルタ (DT_FILTER)、または補助フィルタ (DT_AUXILIARY) 内で使用される場合には、次のストリングトークンが置換されます。

$ISALIST

このプラットフォームで実行可能なネイティブの命令セット (isalist(1) を参照) に展開する。 このトークンを含むパス名は、使用可能な各命令セットに置き換えられる。「命令セット固有の共有オブジェクト」を参照。

上で指定されたパス内あるいは依存関係 (DT_NEEDED) エントリ内で実行時リンカーが使用されると、その実行時リンカーは次のストリングトークンを置き換える。

$ORIGIN

オブジェクトが読み込まれるディレクトリを指定する。通常は、単独のバンドルされていないパッケージ内に依存関係を配置する場合に使用される。「関連する依存関係の配置」を参照

$PLATFORM

現在のマシンの現在のプロセッサタイプに展開 (uname(1) -i を参照) する。「プラットフォーム固有の共有オブジェクト」を参照

$OSNAME

オペレーティングシステムの名前に展開 (uname(1) -s を参照) する。「プラットフォーム固有の共有オブジェクト」を参照

$OSREL

オペレーティングシステムのリリースに展開 (uname(1) -r を参照) する。「プラットフォーム固有の共有オブジェクト」を参照


注 -

$PLATFORM は「Solaris 2.5」に付加されましたが、「Solaris 2.6」より前のものでは、補助フィルタ (DT_AUXILIARY) を表現するためだけに使用できます。「補助フィルタの生成」を参照してください。