JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
リンカーとライブラリ     Oracle Solaris 11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

パート I リンカーおよび実行時リンカーの使用

1.  Oracle Solaris リンカーの紹介

2.  リンカー

3.  実行時リンカー

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

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

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

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

動的ストリングトークン

再配置処理

再配置シンボルの検索

デフォルトのシンボル検索

実行時割り込み

再配置が実行されるとき

再配置エラー

追加オブジェクトの読み込み

動的依存関係の遅延読み込み

dlopen() の代替手段の提供

初期設定および終了ルーチン

初期設定と終了の順序

セキュリティー

実行時リンクのプログラミングインタフェース

追加オブジェクトの読み込み

再配置処理

シンボルの検索

新しいシンボルの入手

機能のテスト

割り込みの使用

デバッグ支援

機能のデバッグ

デバッガモジュール

4.  共有オブジェクト

5.  インタフェースおよびバージョン管理

6.  動的ストリングトークンによる依存関係の確立

パート II クイックリファレンス

7.  リンカーのクイックリファレンス

8.  バージョン管理の手引き

パート III 詳細情報

9.  直接結合

10.  mapfile

11.  拡張性メカニズム

パート IV ELF アプリケーションバイナリインタフェース

12.  オブジェクトファイル形式

13.  プログラムの読み込みと動的リンク

14.  スレッド固有領域 (TLS)

パート V 付録

A.  リンカーとライブラリのアップデートおよび新機能

B.  System V Release 4 (バージョン 1) Mapfile

索引

動的依存関係の遅延読み込み

メモリーに動的オブジェクトが読み込まれる際、その動的オブジェクトに追加の依存関係がないか検査されます。デフォルトでは、存在する依存関係がただちに読み込まれます。このサイクルは、依存関係のツリー全体を使い果たすまで続けられます。最終的に、再配置で指定されたオブジェクト間のデータ参照すべてが解決されます。この処理は、これらの依存関係内のコードが実行中にアプリケーションによって実際に参照されるかどうかに関係なく、行われます。

遅延読み込みモデルでは、遅延読み込みのラベルが付いた依存関係は、明示的に参照が行われるまで読み込まれません。関数呼び出しの遅延結合を利用して、関数が最初に参照されるまで、依存関係の読み込みを延期することができます。結果として、参照されないオブジェクトは読み込まれません。

再配置参照は、即時か遅延です。即時参照はオブジェクトが初期化された時に解決される必要があるため、この参照を満たすすべての依存関係はすぐに読み込まれる必要があります。そのため、そういった依存関係を遅延読み込み可能として示すことは、あまり効果がありません。詳細は、「再配置が実行されるとき」を参照してください。動的オブジェクト間の即時参照は、概してあまり推奨されません。

遅延読み込みは、デバッグライブラリ liblddbg への参照のためにリンカーが使用します。デバッギングを呼び出すことはまれなので、リンカーを呼び出すたびにこのライブラリを読み込むことは不要で、コストがかさみます。このライブラリを遅延読み込みできるように指定することにより、ライブラリの処理コストをデバッギング出力を必要とする読み込みに使うことができます。

遅延読み込みモデルを実行するための代替メソッドは、必要に応じて依存関係に dlopen() または dlsym() を実行することです。このモデルは、dlsym() 参照の数が少ない場合に最適です。またこのモデルは、リンク編集時に依存関係の名前あるいは位置がわからない場合にも適しています。名前や位置がわかっている依存関係のより複雑な相互作用については、通常のシンボル参照のコードを使用し、依存関係を遅延読み込みに指定する方が簡単です。

特定のオブジェクトを遅延読み込み、通常読み込みとして指定するには、リンカーオプション -z lazyload-z nolazyload をそれぞれ使用します。これらのオプションは、リンク編集コマンド行の位置に依存します。このオプションよりあとに指定される依存関係には、このオプションで指定されている読み込み属性が適用されます。デフォルトでは、-z nolazyload オプションが有効です。

次の単純なプログラムでは、libdebug.so.1 に対する依存関係が指定されています。動的セクション (.dynamic) では、libdebug.so.1 に対して遅延読み込みが指定されています。シンボル情報セクション (.SUNW_syminfo) では、libdebug.so.1 の読み込みをトリガーするシンボル参照が指定されています。

$ cc -o prog prog.c -L. -zlazyload -ldebug -znolazyload -lelf -R'$ORIGIN'
$ elfdump -d prog
 
Dynamic Section:  .dynamic
     index  tag           value
       [0]  POSFLAG_1     0x1           [ LAZY ]
       [1]  NEEDED        0x123         libdebug.so.1
       [2]  NEEDED        0x131         libelf.so.1
       [3]  NEEDED        0x13d         libc.so.1
       [4]  RUNPATH       0x147         $ORIGIN
       ...
$ elfdump -y prog
 
Syminfo section: .SUNW_syminfo
     index  flgs        bound to        symbol
      ....
      [52]  DL      [1] libdebug.so.1   debug

値に LAZY が指定された POSFLAG_1 は、次の NEEDED エントリ libdebug.so.1 が遅延読み込みされることを示しています。libelf.so.1 は前に LAZY フラグがないため、このライブラリはプログラムの初期始動時に読み込まれます。


注 - libc.so.1 には、ファイルが遅延読み込みされてはならないという特別なシステム要件があります。libc.so.1 が処理される時点で -z lazyload が有効である場合、フラグは実際には無視されます。


遅延読み込みを使用するには、アプリケーションで使用されるオブジェクト全体に渡り依存関係と「実行パス」を正確に宣言しなければならない場合があります。たとえば、libX.so 内のシンボルを参照する 2 つのオブジェクト libA.solibB.so があるとします。libA.solibX.so を依存関係として宣言しますが、libB.so は宣言しません。通常、libA.solibB.so が併用される場合、libB.solibX.so を参照できます。これは、libA.so によってこの依存関係が利用可能になっているためです。しかし、libX.so が遅延読み込みされるように libA.so で宣言した場合、libB.so がこの依存関係を参照するときに libX.so を読み込めない可能性があります。libB.solibX.so を依存関係として宣言していても、その依存関係の特定に必要な「実行パス」を指定しなかった場合には、同様のエラーが発生する可能性があります。

遅延読み込みに関わらず、動的オブジェクトは、すべての依存関係と依存関係の特定方法を宣言しなければなりません。遅延読み込みでは、この依存情報がより重要な意味合いを持ちます。


注 - 環境変数 LD_NOLAZYLOAD をヌル以外の値に設定すれば、実行時に遅延読み込みを無効にできます。


dlopen() の代替手段の提供

遅延読み込みは、dlopen(3C)dlsym(3C) を使用する代わりになります。「実行時リンクのプログラミングインタフェース」を参照してください。たとえば、libfoo.so.1 の次のコードは、オブジェクトが読み込まれることを確認し、そのオブジェクトのインタフェースを呼び出します。

void foo()
{
    void *handle;

    if ((handle = dlopen("libbar.so.1", RTLD_LAZY)) != NULL) {
        int (*fptr)();

        if ((fptr = (int (*)())dlsym(handle, "bar1")) != NULL)
            (*fptr)(arg1);
        if ((fptr = (int (*)())dlsym(handle, "bar2")) != NULL)
            (*fptr)(arg2);
        ....
}

dlopen()dlsym() を使用するこのモデルは、非常に柔軟ですが、不自然なコーディングスタイルであり、欠点がいくつかあります。

このコードは、必要なインタフェースを提供するオブジェクトが次の条件を満たす場合に、単純化できます。

関数参照が遅延読み込みをトリガーできることを利用すると、libbar.so.1 と同じ遅延読み込みが実現できます。この場合、関数 bar1() を参照すると、関連依存関係が遅延読み込みされます。このコーディングの方が自然です。また、標準関数呼び出しを使用することによって、コンパイラまたは lint(1) で検証できるようになります。

void foo()
{
    bar1(arg1);
    bar2(arg2);
    ....
}
$ cc -G -o libfoo.so.1 foo.c -L. -zdefs -zlazyload -lbar -R'$ORIGIN'

ただし、必要なインタフェースを提供するオブジェクトが常に利用できるとは限らない場合、このモデルは失敗します。この場合、依存関係の名前がわからなくても、その依存関係の有無をテストする機能が必要です。関数参照を満足する依存関係を使用できるかどうかをテストする手段が必要になります。

関数の有無をテストするための堅牢なモデルは、明示的に定義された遅延依存関係を使用することによって、また RTLD_PROBE ハンドルを指定して dlsym(3C) を使用することによって実現できます。

明示的に定義された遅延依存関係は、遅延読み込み可能な依存関係の拡張です。遅延依存関係に関係付けられたシンボル参照は、遅延シンボルと呼ばれます。このシンボルに対する再配置が処理されるのは、シンボルが最初に参照されるときだけです。これらの再配置は、LD_BIND_NOW 処理の一部としても、また RTLD_NOW フラグ付きの dlsym(3C) を介しても処理されません。

遅延依存関係は、リンク編集時にリンカーの -z deferred オプションを使用して確立されます。

$ cc -G -o libfoo.so.1 foo.c -L. -zdefs -zdeferred -lbar -R'$ORIGIN'

遅延依存関係として libbar.so.1 を確立した場合、bar1() への参照によって、その依存関係が利用できることを検証できます。このテストを使用すると、dlsym(3C) を使用した場合と同じ方法で、依存関係によって提供される関数への参照を制御できます。次に、このコードは bar1() および bar2() を自然に呼び出すことができます。これらの呼び出しは判読しやすく、コーディングも容易であるため、コンパイラが呼び出しシーケンスでのエラーを見つけられるようになります。

void foo()
{
    if (dlsym(RTLD_PROBE, "bar1")) {
        bar1(arg1);
        bar2(arg2);
        ....
}

遅延依存関係によって柔軟性が向上します。依存関係がまだ読み込まれていない場合、その依存関係は実行時に変更できます。このメカニズムにより、dlopen(3C) と同じ程度の柔軟性が得られます。つまり、呼び出し元によって、異なるオブジェクトを読み込ませたり、異なるオブジェクトに結合させたりできるようになります。

元の依存関係名が既知の場合、RTLD_DI_DEFERRED 引数を指定して dlinfo(3C) を使用すると、元の依存関係を新しい依存関係と交換できます。また、依存関係に関連する遅延シンボルを使用すると、RTLD_DI_DEFERRED_SYM 引数を持つ dlinfo(3C) を使用して遅延依存関係を特定できます。