リンカーとライブラリ

共有オブジェクト名の記録

動的実行可能ファイルまたは共有オブジェクトでの依存関係の記録は、デフォルトでは、関連する共有オブジェクトがリンカーによって参照されるときのファイル名になります。たとえば、次の動的実行可能ファイルは、同じ共有オブジェクト libfoo.so に対して構築されますが、同じ依存関係の解釈は異なります。


$ cc -o ../tmp/libfoo.so -G foo.o
$ cc -o prog main.o -L../tmp -lfoo
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so

$ cc -o prog main.o ../tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   ../tmp/libfoo.so

$ cc -o prog main.o /usr/tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   /usr/tmp/libfoo.so

上記の例が示すように、依存関係を記録するこのメカニズムでは、コンパイル手法の違いによって不一致が生じる可能性があります。また、リンク編集中に参照される共有オブジェクトの位置が、インストールされたシステムでの共有オブジェクトの最終的な位置と異なる場合があります。依存関係を指定するより一貫した手法として、共有オブジェクトは、それぞれの内部にファイル名を記録できます。共有オブジェクトは、このファイル名によって実行時に参照されます。

共有オブジェクトのリンク編集中、-h オプションを使用すると、その実行時名を共有オブジェクト自体に記録できます。次の例では、共有オブジェクトの実行時名 libfoo.so.1 は、ファイル自体に記録されます。この識別名は、soname と呼ばれます。


$ cc -o ../tmp/libfoo.so -G -K pic -h libfoo.so.1 foo.c

次の例は、dump(1) を使用して SONAME タグを持つエントリを参照し、soname の記録を表示する方法を示しています。


$ dump -Lvp ../tmp/libfoo.so

../tmp/libfoo.so:
[INDEX] Tag      Value
[1]     SONAME   libfoo.so.1
.........

リンカーが soname を含む共有オブジェクトを処理する場合、生成中の出力ファイル内に依存関係として記録されるのはこの名前です。

前の例から動的実行可能ファイル prog を作成しているときに、この新しいバージョンの libfoo.so が使用されると、実行可能ファイルを作成するための 3 つの方式すべてによって同じ依存関係が記録されます。


$ cc -o prog main.o -L../tmp -lfoo
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

$ cc -o prog main.o ../tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

$ cc -o prog main.o /usr/tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

上記の例では、-h オプションは、単純 (simple) ファイル名を指定するために使用されます。つまり、名前に「/」が付きません。この規約では、実行時リンカーが規則を使用して実際のファイルを検索できます。詳細については、共有オブジェクトの依存関係の検索を参照してください。

アーカイブへの共有オブジェクトの取り込み

共有オブジェクトに soname を記録するメカニズムは、共有オブジェクトがアーカイブライブラリから処理される場合に重要です。

アーカイブは、1 つまたは複数の共有オブジェクトから構築し、動的実行可能ファイルまたは共有オブジェクトを生成するために使用できます。共有オブジェクトは、リンク編集の条件を満たすためにアーカイブから抽出できます。作成中の出力ファイルに連結される再配置可能オブジェクトの処理とは違って、アーカイブから抽出された共有オブジェクトは、すべて依存関係として記録されます。アーカイブ抽出の条件の詳細については、アーカイブ処理 を参照してください。

アーカイブ構成要素の名前はリンカーによって構築されて、アーカイブ名とアーカイブ内のオブジェクトの連結になります。次に例を示します。


$ cc -o libfoo.so.1 -G -K pic foo.c
$ ar -r libfoo.a libfoo.so.1
$ cc -o main main.o libfoo.a
$ dump -Lv main | grep NEEDED
[1]     NEEDED   libfoo.a(libfoo.so.1)

この連結名を持つファイルが実行時に存在することはほとんどないため、共有オブジェクト内に soname を与える方法が、依存関係の有意な実行時ファイル名を生成する唯一の手段です。


注 –

実行時リンカーは、アーカイブからオブジェクトを抽出しません。したがって、上記の例では、必要な共有オブジェクト依存関係をアーカイブから抽出して、実行時環境で使用できるようにする必要があります。


記録名の衝突

共有オブジェクトが実行可能ファイルまたは別の共有オブジェクトを作成するために使用される場合、リンカーは、いくつかの整合性検査を実行して、出力ファイル内に記録される依存関係名すべてが一意になるように保証します。

依存関係名の衝突は、リンク編集への入力ファイルとして使用される 2 つの共有オブジェクトがどちらも同じ soname を含む場合に発生する可能性があります。次に例を示します。


$ cc -o libfoo.so -G -K pic -h libsame.so.1 foo.c
$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c
$ cc -o prog main.o -L. -lfoo -lbar
ld: fatal: recording name conflict: file `./libfoo.so' and \
    file `./libbar.so' provide identical dependency names: libsame.so.1
ld: fatal: File processing errors. No output written to prog

記録された soname を持たない共有オブジェクトのファイル名が、同じリンク編集中に使用された別の共有オブジェクトの soname に一致する場合にも同様のエラー状態が発生します。

生成中の共有オブジェクトの実行時名が、その依存関係の 1 つに一致する場合にも、リンカーは名前の衝突を報告します。次に例を示します。


$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c -L. -lfoo
ld: fatal: recording name conflict: file `./libfoo.so' and \
    -h option provide identical dependency names: libsame.so.1
ld: fatal: File processing errors. No output written to libbar.so