共有オブジェクトと実行時リンク
デフォルトにより、プログラムのリンクは、共有オブジェクトからインポートされたシンボ ルへの参照がロード時にその定義にバインドされるように行われます。
このことは、プログラムもしくは、 プログラムによって必要とされる別の共有オブジェクトが同じ シンボルを定義している場合であっても、当てはまります。
- 実行時リンカー
- 適切にリンクされたプログラム用にシンボルの再バインドを可能にする、 共有オブジェクト。
プログラムを - brtl オプションとリンクすることにより、実行時リンカーをプログラムに組み込みます。 このオプションには、以下に示す効果があります。
- 実行時リンカーへの参照がプログラムに 追加される。 プログラムの実行が開始されると、開始コード (/lib/crt0.o) は、 main 関数が呼び出される前に実行時リンカーを呼び出します。
- 共有オブジェクトであるすべての入力ファイルが、 プログラムのローダー・セクション内のプログラムの従属としてリストされる。 共有オブジェクトは、コマンド・ラインで指定した順にリストされます。 その結果、システム・ローダーはそれらの共有オブジェクトをすべてロードして、 実行時リンカーがそれらの定義を使用できるようにします。 - brtl オプションが使用されていない場合、プログラムによって使用される別の共用オブジェクトが必要とする定義を提供している場合でも、プログラムによって参照されない共有オブジェクトはリストされません。
- アーカイブに収められた共有オブジェクトは、共有オブジェクトのメンバーに対してアーカイブが自動ロードを指定している場合に限ってリストされます。 アーカイブ・メンバー foo.o の自動ロードは、以下の行を持つファイルを作成することによって指定します。
そのファイルをメンバーとしてアーカイブに追加することによって行います。# autoload #! (foo.o) - ダイナミックモードでは、-lフラグで指定した入力ファイルは、.soおよび.aで終わる場合があります。 つまり、 -lfoo への参照は、検索対象のディレクトリーのいずれかで検出された最初の libfoo.so または libfoo.a によって満たされます。 -bstatic オプションが使用されていない限り、デフォルトで動的モードが有効になっています。
実行時リンカーは、静的リンクが使用されるときの ld コマンドの動作を模倣します。ただし、シンボルの解決に使用できるのは、エクスポートされたシンボルのみを使用する点です。 実行時リンクを使用するときでも、 システム・ローダーは、主プログラム内とそれが依存するすべてのモジュール内の すべてのシンボル参照を、ロードし、解決できなければなりません。 したがって、定義がモジュールから除去され、 主プログラムにこの定義の参照がある場合は、その シンボルの別の定義が別のモジュールに存在していても、 このプログラムは実行しません。
実行時リンカーは、別のモジュールからインポートされたシンボルへのすべての参照を 再バインドすることができます。 該当の参照と同じモジュールで定義された シンボルへの参照は、そのシンボルについて実行時リンクが使用可能になっている状態で そのモジュールが作成された場合にのみ、再バインドすることができます。
AIX® 4.2以降で出荷される共有モジュールは、ほとんどのエクスポートされた変数に対してランタイムリンクが有効になっています。 関数の 実行時リンクは、関数ポインターによって呼び出された関数の場合のみ 使用可能になっています。 たとえば、出荷時には、/lib/libc.a内の共有オブジェクトshr.o内のmallocサブルーチンへの呼び出しは、メインプログラムまたは別の共有モジュールにmallocの定義が存在していても、リバウンドできません。 ほとんどの出荷済み共有モジュールをリンクすることで、 rtl_enable コマンドを実行することにより、関数および変数のランタイム・リンクを有効にすることができます。
実行時リンカーの操作
主プログラムのロードと解決は、システム・ローダーによって通常の方法で行われます。 何らかの理由で実行可能プログラムをロードできない場合、 exec() サブルーチンは失敗し、実行時リンカーはまったく呼び出されません。 主プログラムが正常にロードされると、制御は 実行時リンカーに移り、実行時リンカーが以下の説明のようにシンボルを 再バインドします。 実行時リンカーが完了すると、該当する場合は、 初期化ルーチンが呼び出されてから、main 関数が呼び出されます。
実行時リンカーは、各モジュールのローダー・セクションにリストされた 従属モジュールの順序に従って、主実行可能モジュールから始まり、 主実行可能モジュールの直接従属に続く、 幅優先検索順序でモジュールを処理します。 この順序は、シンボルの定義インスタンスを 検索するときも使用されます。 シンボルの「定義インスタンス」は、通常はシンボルの最初のインスタンスですが、 例外が 2 つあります。 シンボルの最初のインスタンスが未解決で、据え置きのインポートの場合は、 定義インスタンスは存在しません。 最初のインスタンスが BSS シンボル (つまり、タイプが XTY_CMで、未初期化変数を示す ) である場合に、 BSS シンボルでも未解決の据え置きインポートでもないシンボルの別のインスタンスが存在する場合、シンボルの最初のインスタンスは定義インスタンスになります。
各モジュールのローダー・セクションは、インポートされた シンボル (通常は別の指定されたモジュールで定義される) と エクスポートされたシンボル (通常はモジュール自体で定義される) をリストします。 インポートされ、エクスポートされるシンボルは、 「パススルーされた」インポートと呼ばれます。 このようなシンボルは、1 つのモジュールで定義されているように見えますが、 実際は、別のモジュールで定義されます。
シンボルには、「据え置きインポート」とマークすることもできます。 据え置きインポート・シンボルへの参照は、 実行時リンカーによって再バインドされることはありません。 これらのシンボルの解決は、 loadbind() を呼び出すか、または load() または dlopen()で明示的に新しいモジュールをロードすることによって、システム・ローダーによって実行される必要があります。
インポート・シンボル (据え置きインポート以外のもの) は、 常に再バインドすることができます。 システム・ローダーは、既にほとんどのインポートを解決しています。 各インポート・シンボルへの参照は、 シンボルの定義インスタンスに再バインドされます。 定義インスタンスが存在しない場合は、 エラー・メッセージが標準エラーに出力されます。 さらに、インポート・シンボルのタイプ・チェック・ハッシュ文字列が、 定義シンボルのハッシュ文字列と一致しない場合は、 エラー・メッセージが出力されます。
エクスポート・シンボルへの参照も、 その参照がローダー・セクションの再配置テーブルに現れる 場合は、その定義インスタンスに再バインドされます。 (上記の説明のように、パススルーされたインポートは、 ほかのインポートとともに処理されます。) モジュールがリンクされた方法によっては、 エクスポート・シンボルへの参照の中には、リンク時に バインドされ、再バインドできない場合もあります。 エクスポート・シンボルは、エクスポート・モジュールで定義されるため、 最初のインスタンスが据え置きインポートでない限り、 シンボルの定義インスタンスは常に存在します。したがって、 エクスポート・シンボルの再バインド時のエラーの可能性は低くなりますが、 依然として残ります。 インポートの場合のように、 シンボルの再バインド時にタイプ・チェック・ハッシュ文字列が一致し ない場合は、エラーが出力されます。
シンボルの再バインド時には、必ず、そのシンボルを使用するモジュールから、 そのシンボルを定義するモジュールへ依存関係が追加されます。 この依存関係があるため、 モジュールが早まってアドレス・スペースから除去されることはありません。 これは、 dlopen サブルーチンによってロードされたモジュールが、 dlclose サブルーチンでモジュールをアンロードしようとするときに使用されているシンボルを定義する場合に重要です。
ローダー・セクション・シンボル・テーブルには、 シンボルの桁合わせまたは長さに関する情報は入っていません。 したがって、シンボルが、短すぎたり、 あるいは桁合わせが適切でないインスタンスに 再バインドされても、エラーは検出されません。 この場合は、実行エラーが起こることがあります。
すべてのモジュールが処理されると、ランタイム・リンカーは、ランタイム・リンク・エラーが発生した場合に exit サブルーチンを呼び出し、以下の終了コードを渡します。144(0x90). それ以外の場合は、初期設定ルーチンまたは main()の呼び出しにより、
ランタイム・リンクが使用可能に設定された共有オブジェクトの作成
実行時リンク用に使用可能にされた共用オブジェクトを作成するには、 -G フラグとリンクします。 このフラグが使用されると、以下のアクションが起こります。
- エクスポートされたシンボルは、nosymbolicシンボルへのすべての参照が実行時リンカーによって再バインドできるようにします。
- 未定義のシンボルが許可されます ( -berok オプションを参照してください ) 。 このようなシンボルには、シンボル・モジュール名 ".." からインポートされたという マークが付けられます。 ".."からインポートされたシンボルは、 システム・ローダーが解決しないため、使用する前に実行時リンカーによって解決しておく 必要があります。
- 出力ファイルには、以下のモジュール・タイプが与えられます。SREあたかも-bM:SREオプションが指定されたかのように。
- コマンド行にリストされているすべての共用オブジェクトは、出力モジュールの従属としてリストされます。これは、プログラムを - brtl オプションとリンクする場合と同じ方法で行われます。
- アーカイブ内の共有オブジェクトがリストされるのは、autoload属性。
-G フラグによって暗黙指定される -berok オプションを使用すると、リンク時に検出される可能性のあるエラーをマスクできます。 モジュールをリンクするときに、参照されるすべてのシンボルを定義する場合は、 -G フラグの後に -bernotok オプションを使用する必要があります。 こうすれば、未定義シンボルに関してエラーが報告されます。