リンカーとライブラリ

再配置が実行されるとき

再配置は、再配置が実行されるタイミングで 2 つのタイプに区別できます。このような、再配置されたオフセットに対して行われる「参照」のタイプによって、次のように区別されます。

「即時参照」とは、オブジェクトが読み込まれたときにただちに決定しなければならない再配置のことです。この参照は、一般にオブジェクトコードで使用されるデータ項目、関数ポインタ、および位置依存共有オブジェクトからの関数呼び出しに対するものです。即時参照では、再配置された項目が参照されたことを実行時リンカーは認識できません。このため、すべての即時参照は、オブジェクトが読み込まれたら、アプリケーションが制御を獲得または再獲得する前に、再配置が完了する必要があります。

「遅延参照」とは、オブジェクトの実行時に決定できる再配置のことです。通常は、位置独立共有オブジェクトから大域関数への呼び出しか、動的実行可能ファイルから外部関数への呼び出しです。遅延参照を行う動的モジュールをコンパイルおよびリンク編集しているときに、関連付けられた関数呼び出しは、プロシージャーリンクテーブルのエントリへの呼び出しに変換されます。これらのエントリは、.plt セクションを構成します。プロシージャーリンクテーブルの各エントリは、関連付けられた再配置を伴う遅延参照になります。

プロシージャーリンクテーブルの特定のエントリに対する最初の呼び出しの実行中に、制御が実行時リンカーに渡されます。実行時リンカーは、関連付けられたオブジェクト内で必要なシンボルを検索し、エントリ情報を書き換えます。その後のプロシージャーリンクテーブルのエントリへの呼び出しは、直接関数に対して行われます。遅延参照では、関数が最初に呼び出されるまで、再配置を遅延させることができます。この処理は、「遅延」結合と呼ばれることがあります。

実行時リンカーのデフォルトモードは、プロシージャーリンクテーブルの再配置が行われるたびに遅延結合を実行する、というものです。デフォルトモードを無効にするには、環境変数 LD_BIND_NOW にヌル以外の任意の値を設定します。この環境変数の設定により、実行時リンカーは、オブジェクトが読み込まれた時点で、即時参照と遅延参照を両方とも再配置します。これらの再配置は、アプリケーションが制御を獲得または再獲得するまでの間に行われます。たとえば、環境変数を次のように設定して、ファイル prog とその依存関係内のすべての再配置が行われるとします。これらの再配置は、制御がアプリケーションに移る前に行われます。


$ LD_BIND_NOW=1 prog

オブジェクトへのアクセスは、RTLD_NOW として定義されたモードを指定して dlopen(3C) を使用することによっても行えます。リンカーの -z now オプションを使用してオブジェクトを構築すれば、オブジェクトが読み込まれたときに再配置処理を完了させる必要があることを示すことができます。この再配置要件は、実行時に指定したオブジェクトの依存先すべてに波及します。


注 –

前述の即時参照と遅延参照の例は、標準的なものです。ただし、プロシージャーリンクテーブルのエントリの作成は、リンク編集の入力として使用する再配置可能オブジェクトファイルが提供する再配置情報によって、最終的に制御されます。R_SPARC_WPLT30R_386_PLT32 などの再配置レコードには、プロシージャーリンクテーブルのエントリの作成が指定されています。こうした再配置は、位置独立のコードで共通です。

ただし、通常、動的実行可能ファイルは位置に依存するコードから作成されるため、プロシージャーリンクテーブルのエントリが必要であることを示さない場合があります。動的実行可能ファイルの位置は固定されているため、参照が外部関数定義に結合された時点で、リンカーはプロシージャーのリンクテーブルを作成できます。元の再配置レコードに関係なく、このプロシージャーリンクテーブルのエントリを作成できます。