リンカーとライブラリ

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

前の項では、実行時リンカーが、動的実行プログラムとその依存関係からのプロセスを、各モジュールのリンク編集中に定義されたように初期設定する方法について説明しました。また、実行時リンカーでは、プロセスの初期設定中に新しいオブジェクトを採用できるという、一歩進んだ柔軟性も提供しています。

環境変数 LD_PRELOAD は、共有オブジェクトまたは再配置可能なオブジェクトのフレーム名、あるいは複数のフレーム名を空白で区切ったストリングに初期設定できます。これらのオブジェクトは、動的実行プログラムのあとで、依存関係よりもまえに対応付けされ、ワールド検索範囲と大域シンボル可視性が割り当てられます (「シンボル検索」を参照)。次に例を示します。


$ LD_PRELOAD=./newstuff.so.1 prog

ここでは、動的実行プログラム prog が対応付けされ、次に共有オブジェクト newstuff.so.1 が続き、その次に prog 内に定義された依存関係が続きます。これらのオブジェクトが処理される順番は、ldd(1) を使用して表示できます。


$ LD_PRELOAD=./newstuff.so.1 ldd prog
        ./newstuff.so.1 => ./newstuff.so
        libc.so.1 =>     /usr/lib/libc.so.1

次に別の例を示します。


$ LD_PRELOAD="./foo.o ./bar.o" prog

この例の事前読み込みは、少し複雑で時間がかかります。実行時リンカーは、最初に再配置可能オブジェクト foo.obar.o をリンク編集し、メモリー内に保持されていた共有オブジェクトを生成します。次にこのメモリーイメージは、この前の例で示した共有オブジェクト newstuff.so.1 の事前読み込みとまったく同じ方法で、動的実行プログラムとその依存関係との間に挿入されます。ここでも、これらのオブジェクトが処理される順番は、ldd(1) を使用して表示できます。


$ LD_PRELOAD="./foo.o ./bar.o" ldd prog
        ./foo.o =>       ./foo.o
        ./bar.o =>       ./bar.o
        libc.so.1 =>     /usr/lib/libc.so.1

オブジェクトを動的実行プログラムのあとに挿入するこれらのメカニズムは、「挿入」で説明した挿入の概念を別のレベルに受け継いだものです。これらのメカニズムを使用すると、標準的な共有オブジェクト内に常駐する関数の、新しいインプリメンテーション (実現) を試すことができます。この関数が組み込まれたオブジェクトをあらかじめ読み込むことにより、この関数は元のオブジェクトにも挿入されます。そのため、古い関数は、新しく読み込まれたバージョンによって完全に隠れてしまいます。

この他にも事前読み込みは、標準的な共有オブジェクト内に常駐する関数を補強するために使用できます。これが、新しいシンボルを元のシンボルに挿入する目的です。これにより、新しい関数は、元の関数への呼び出し機能も保持しながら、この他の処理も追加実行できます。このメカニズムには、元の関数に関連したシンボルエイリアスか (「単純な解析」を参照)、または元のシンボルのアドレスを検索する機能が必要です (「割り込みの使用」を参照)。