リンカーとライブラリ

位置に依存しないコード

実行時に必要なページ変更が最も少ないプログラムを作成するために、コンパイラは、-K pic オプションによって、位置に依存しないコードを生成します。動的実行可能ファイル内のコードは、通常、メモリー内の固定アドレスに結合されていますが、位置に依存しないコードは、プロセスのアドレス空間内にある任意の場所に読み込みできます。このコードは、特定のアドレスに結合されていないため、それを使用する各プロセスの異なるアドレスでページ変更を行わなくても、正しく実行されます。

位置に依存しないコードを使用すると、再配置可能な参照が、共有オブジェクトのデータセグメント内のデータを使用する間接参照の形式で生成されます。この結果、テキストセグメントコードは読み取り専用のままになり、すべての再配置更新がデータセグメント内の対応するエントリに適用されます。これらの 2 つのセクションの使用方法については、「大域オフセットテーブル (プロセッサ固有)」「プロシージャのリンクテーブル (プロセッサ固有)」を参照してください。

共有オブジェクトが位置に依存しないコードから構築される場合、テキストセグメントでは通常、実行時に大量の再配置を実行する必要があります。この再配置を処理するために実行時リンカーが用意されていますが、この処理によるシステムオーバーヘッドによって深刻な性能低下が生じるおそれがあります。

テキストセグメントに対して再配置を必要とする共有オブジェクトは、dump(1) を使用して、TEXTREL エントリの出力を調べることによって識別できます。次に例を示します。


$ cc -o libfoo.so.1 -G -R. foo.c
$ dump -Lv libfoo.so.1 | grep TEXTREL
[9]     TEXTREL  0

注 -

TEXTREL エントリの値は不適切です。共有オブジェクトにこの値が存在する場合は、テキスト再配置があることを示しています。


テキスト再配置を含む共有オブジェクトの作成を防止するには、リンカーの -z text フラグを使用することをお勧めします。このフラグを使用すると、リンカーは、入力として使用された、位置に依存しないコード以外のコードのソースを示す診断を生成し、意図した共有オブジェクトの生成は失敗に終わります。次に例を示します。


$ cc -o libfoo.so.1 -z text -G -R. foo.c
Text relocation remains                       referenced
    against symbol                  offset      in file
foo                                 0x0         foo.o
bar                                 0x8         foo.o
ld: fatal: relocations remain against allocatable but ¥
non-writable sections

ここでは、ファイル foo.o から位置に依存しないコード以外のコードが生成されたために、テキストセグメントに対して 2 つの再配置が生成されています。これらの診断は、可能な場合、再配置の実行に必要なシンボリック参照すべてを示します。この場合、再配置はシンボル foobar に対するものです。

-K pic オプションを使用しないという原因以外で、共有オブジェクトの生成時にテキスト再配置が作成される最も一般的な原因は、位置に依存しない適切なプロトタイプによって符号化されていない手書きアセンブラコードを含めているというものです。


注 -

中間アセンブラファイルを生成するコンパイラ機能を使用すると、いくつかの単純なテストケースソースファイルを試すことによって、位置からの独立性を有効にするために使用されるコーディング手法がわかります。


プロセッサによっては、位置に依存しないフラグの 2 つ目の形式として -K PIC も使用できます。このフラグを使用すると、追加コードによるオーバーヘッドと引き換えに、より多数の再配置を処理できます (詳細については、cc(1) を参照)。