リンカーとライブラリ

バージョン結合の指定

バージョン定義を含む共有オブジェクトに対して動的オブジェクトを作成する場合、リンカーに対して、特定のバージョン定義への結合を制限するように指示することができます。リンカーを使用すると、特定インタフェースへのオブジェクトの結合を効果的に制御することができます。

オブジェクトの結合要件は、「ファイル制御指令」によって制御できます。この指令は、リンカーの -M オプションと関連の mapfile を使用して提供されます。ファイル制御指令には、次の構文を使用します。


name - version [ version ... ] [ $ADDVERS=version ];

バージョン結合の制御は、次のような場合に役立ちます。

次に、バージョン制御メカニズムの使用例を示します。この例では、次のバージョンインタフェース定義を含む共有オブジェクト libfoo.so.1 を使用しています。


$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:
                foo1;
                foo2;
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;

バージョン定義 SUNW_1.1 および SUNW_1.2 は、ソフトウェア Release X および Release X+1 で使用可能な libfoo.so.1 内のインタフェースをそれぞれ表します。

アプリケーションは、次のバージョン制御 mapfile 指令を使用して、Release X で使用可能なインタフェースだけに結合するように構築できます。


$ cat mapfile
libfoo.so - SUNW_1.1;

たとえば、Release X 上で動作するアプリケーション prog を開発するとします。アプリケーションでは、Release X で使用可能なインタフェース以外は使用できません。シンボル bar を間違えて参照すると、アプリケーションは要求されるインタフェースに準拠しなくなります。リンカーはこの状態を未定義のシンボルエラーとして通知します。


$ cat prog.c
extern void foo1();
extern void bar();

main()
{
        foo1();
        bar();
}
$ cc -o prog prog.c -M mapfile -L. -R. -lfoo
Undefined           first referenced
 symbol                 in file
bar                     prog.o  (symbol belongs to unavailable \
                                version ./libfoo.so (SUNW_1.2))
ld: fatal: Symbol referencing errors. No output written to prog

SUNW_1.1 インタフェースに準拠するには、bar への参照を削除する必要があります。これは、アプリケーションを再処理して bar に対する要件を削除するか、または bar の実装をアプリケーションの作成に追加することによって行います。


注 –

デフォルトでは、リンク編集の一部として検出された共有オブジェクト依存関係も、すべてのファイル制御指令に対して確認されます。環境変数 LD_NOVERSION を使用して、共有オブジェクト依存関係のバージョン検査を抑制します。


追加バージョン定義への結合

通常のオブジェクトシンボル結合から作成されるバージョン依存関係に、追加のバージョン依存関係を記録するには、$ADDVERS ファイル制御指令を使用します。次の節では、この追加結合が役に立ついくつかのシナリオについて説明します。

インタフェースの再定義

1 つのシナリオは、ISV 固有のインタフェースを公開標準インタフェースで使用します。

libfoo.so.1 の例に続いて、Release X+2 において、バージョン定義 SUNW_1.1 が 2 つの標準リリース STAND_ASTAND_B に分割される場合を想定します。互換性を維持するには、SUNW_1.1 バージョン定義を維持する必要があります。次の例では、このバージョン定義は 2 つの標準定義を継承するものとして表されています。


$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:           {STAND_A, STAND_B}:
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;
        STAND_A:
                foo1;
                STAND_A;
        STAND_B:
                foo2;
                STAND_B;

アプリケーション prog の唯一の要件がインタフェースシンボル foo1 である場合、このアプリケーションはバージョン定義 STAND_A に対して単一の依存関係を持ちます。このことは、libfoo.so.1Release X+2 よりも小さいシステムでの prog の実行を阻害します。以前のリリースでは、インタフェース foo1 が存在する場合でも、バージョン定義 STAND_A は存在しませんでした。

アプリケーション prog は、SUNW_1.1 に対する依存関係を作成することによって、その要件を以前のリリースに合わせて構築できます。


$ cat mapfile
libfoo.so - SUNW_1.1 $ADDVERS=SUNW_1.1;
$ cat prog
extern void foo1();

main()
{
        foo1();
}
$ cc -M mapfile -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (SUNW_1.1);

この明示的な依存関係は、真の依存関係の要件をカプセル化するのに十分です。この依存関係は古いリリースとの互換性も保ちます。

ウィークバージョンの結合

「ウィークバージョン定義の作成」では、ウィークバージョン定義を使用して、内部実装の変更をマークする方法について説明しました。これらのバージョン定義は、オブジェクトに対して行われたバグ修正と性能の改善に適しています。ウィークバージョンの存在が必要である場合、ウィークバージョン定義への明示的な依存関係を作成できます。オブジェクトを正しく機能させるためにバグ修正や性能の改善が重要な場合、このような依存関係の作成も重要になります。

上記の libfoo.so.1 の例で、バグ修正がウィークバージョン定義 SUNW_1.2.1 としてソフトウェア Release X+3 に組み込まれている場合を想定します。


$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:           {STAND_A, STAND_B}:
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;
        STAND_A:
                foo1;
                STAND_A;
        STAND_B:
                foo2;
                STAND_B;
        SUNW_1.2.1 [WEAK]:  {SUNW_1.2}:
                SUNW_1.2.1;

通常、アプリケーションは、この libfoo.so.1 に対して構築されている場合、バージョン定義 SUNW_1.2.1 に対する弱い依存関係を記録します。この依存関係は情報提供だけを目的とします。実行時に使用される libfoo.so.1 の実装にバージョン定義が見つからなくても、この依存関係によってアプリケーションが強制終了されることはありません。

ファイル制御指令 $ADDVERS を使用すると、バージョン定義に対する明示的な依存関係を生成できます。この定義がウィークである場合、この明示的参照によって、バージョン定義が強い依存関係に高められます。

アプリケーション prog は、次のファイル制御指令を使用して、SUNW_1.2.1 インタフェースを実行時に使用できるという要件を実施するように構築できます。


$ cat mapfile
libfoo.so - SUNW_1.1 $ADDVERS=SUNW_1.2.1;
$ cat prog
extern void foo1();

main()
{
        foo1();
}
$ cc -M mapfile -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (SUNW_1.2.1);

prog には、インタフェース STAND_A に対する明示的な依存関係があります。バージョン定義 SUNW_1.2.1 は、強いバージョンに高められているため、依存関係 STAND_A によって正規化されます。実行時にバージョン定義 SUNW_1.2.1 が見つからないと、重大なエラーが生成されます。


注 –

依存関係が少ない場合、リンカーの -u オプションを使用して、バージョン定義に明示的に結合できます。このオプションで、バージョン定義シンボルを参照します。ただし、シンボル参照は非選択的です。類似の名前を持つ複数のバージョン定義を含む可能性がある複数の依存関係を処理する場合は、この手法で明示的な結合を作成できないことがあります。