リンカーとライブラリ

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

また、実行時リンカーでは、プロセスの初期化中に新しいオブジェクトを取り込めるという、一歩進んだ柔軟性も提供しています。

環境変数 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

オブジェクトを動的実行プログラムの後に挿入するこれらの機構は、別のレベルへ割り込むという発想に基づいています。これらの機構を使用すると、標準的な共有オブジェクト内に存在する関数の、新しい実装を試すことができます。この関数が組み込まれたオブジェクトをあらかじめ読み込むことにより、このオブジェクトは元のオブジェクトに割り込みます。そして、古い関数は、事前読み込みされた新しい関数によって完全に隠されてしまいます。

この他にも事前読み込みは、標準的な共有オブジェクト内に常駐する関数を補強するために使用できます。新しいシンボルが元のシンボルに割り込むことで、元の関数への呼び出し機能を保持しながら、新しい関数はいくつかの追加処理を実行できます。この機構には、元の関数に関連したシンボルエイリアスか、または元のシンボルのアドレスを検索する機能が必要です。