シンボル・プリエンプション

共有可能なオブジェクトの関数やデータ項目を使用するときに、それらの代わりに独自に定義したものを使用することができます。 例えば、標準 C ランタイム・ライブラリの共有可能なオブジェクト libc.so を使用するときに、独自のヒープ管理ルーチン malloc() および free() の定義を使用することができます。 この場合、lib.so 内の malloc() および free() への呼び出しが libc.so にある定義ではなく独自のルーチンの定義を呼び出すことが重要です。 独自の定義は、共有可能なオブジェクト内の定義を無効に (プリエンプト) します。

共有可能なオブジェクトのこの特徴は、シンボル・プリエンプションと呼ばれます。 ランタイム・ローダがコンポーネントをロードするとき、コンポーネント内の default 可視属性のシンボルはすべて、既にロードされているコンポーネント内の同じ名前のシンボルによるプリエンプションに従います。 メイン・プログラム・イメージは常に最初にロードされるので、メイン・プログラムが定義するシンボルはプリエンプトされません。

default 可視属性のシンボルは実行時までメモリアドレスにバインドされないため、シンボル・プリエンプションが発生する可能性により多くのコンパイラの最適化は禁止されます。例えば、default 可視属性のルーチンへの呼び出しは、コンパイル単位が共有可能なオブジェクトにリンクされた場合にプリエンプトされるため、インライン展開することができません。 プリエンプト可能なデータシンボルは、名前が異なるコンポーネント中のシンボルにバインドされるため、GP-相対アドレス指定を使用してアクセスすることはできません。GP-相対アドレスはコンパイル時にはわかりません。

シンボル・プリエンプションは、コンパイラの最適化と全く逆の効果であるため、ほとんど使用されていない機能です。 この理由のため、コンパイラはすべてのグローバル・シンボル定義をデフォルトでプリエンプト可能ではない (つまり、protected 可視属性) として扱います 。 他のコンパイル単位で定義されているシンボルへのグローバル参照は、デフォルトでプリエンプト可能である (つまり、default 可視属性) と仮定されます。 すべてのグローバル定義や参照をプリエンプト可能にする場合は、このデフォルトを無視する -fpic オプションを指定してください。