ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
Oracle Solaris 11.1 リンカーとライブラリガイド Oracle Solaris 11.1 Information Library (日本語) |
7. システムのパフォーマンスを最適化するオブジェクトの構築
パート IV ELF アプリケーションバイナリインタフェース
再配置は、シンボル参照をシンボル定義に関連付ける処理です。たとえば、プログラムが関数を呼び出すとき、関連付けられている呼び出し命令は、実行時に適切な宛先アドレスに制御を渡さなければなりません。再配置可能ファイルには、セクション内容の変更方法を示す情報が存在しなければなりません。この情報により、実行可能オブジェクトファイルと共有オブジェクトファイルは、プロセスのプログラムイメージに関する正しい情報を保持できます。再配置エントリは、これらのデータを保持します。
再配置エントリは、次の構造体を持つことができます。sys/elf.h を参照してください。
typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; } Elf32_Rel; typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; Elf32_Sword r_addend; } Elf32_Rela; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; } Elf64_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; Elf64_Sxword r_addend; } Elf64_Rela;
このメンバーは、再配置処理を適用する位置を与えます。オブジェクトファイルが異なると、このメンバーの解釈が多少異なります。
再配置可能ファイルの場合、値はセクションのオフセットを示します。再配置セクション自身はファイルの別セクションの変更方法を示します。再配置オフセットは、2 番目のセクション内のストレージを指定します。
実行可能ファイルまたは共有オブジェクトの場合、値は再配置の影響を受けるストレージユニットの仮想アドレスを示します。この情報により、再配置エントリは、実行時リンカーにとって、より意味のあるものになります。
関連するプログラムによるアクセスの効率を高めるため、メンバーの解釈はオブジェクトファイルによって異なりますが、再配置タイプの意味は同じになります。
このメンバーは、再配置が行われなければならないシンボルテーブルインデックスと、適用される再配置の種類を与えます。たとえば、呼び出し命令の再配置エントリは、呼び出される関数のシンボルテーブルインデックスを保持します。インデックスが STN_UNDEF (未定義シンボルインデックス) の場合、再配置はシンボル値として 0 を使用します。
再配置の種類はプロセッサに固有です。再配置エントリの再配置の種類またはシンボルテーブルインデックスは、それぞれ ELF32_R_TYPE または ELF32_R_SYM をエントリの r_info メンバーに適用した結果です。
#define ELF32_R_SYM(info) ((info)>>8) #define ELF32_R_TYPE(info) ((unsigned char)(info)) #define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) #define ELF64_R_SYM(info) ((info)>>32) #define ELF64_R_TYPE(info) ((Elf64_Word)(info)) #define ELF64_R_INFO(sym, type) (((Elf64_Xword)(sym)<<32)+ \ (Elf64_Xword)(type))
64 ビット SPARC Elf64_Rela 構造の場合、r_info フィールドはさらに 8 ビットの識別子と 24 ビットの付随的なデータに分割されます。既存の再配置タイプの場合、データフィールドはゼロになります。これに対し、新しい再配置タイプの場合には、データビットが使用される可能性があります。
#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) #define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) #define ELF64_R_TYPE_INFO(data, type) (((Elf64_Xword)(data)<<8)+ \ (Elf64_Xword)(type))
このメンバーは、再配置可能フィールドに格納される値の計算に使用される定数加数を指定します。
Rela エントリには、明示的加数が含まれます。Rel エントリには、変更される位置に暗黙の加数が存在します。32 ビット SPARC では、Elf32_Rela 再配置エントリのみを使用します。64 ビット SPARC および 64 ビット x86 では、Elf64_Rela 再配置エントリのみを使用します。したがって、r_addend メンバーは再配置加数として機能します。x86 は、Elf32_Rel 再配置エントリのみを使用します。再配置対象のフィールドは、加数を保持します。すべての場合において、加数と計算された結果は同じバイト順序を使用します。
再配置セクションは、ほかに 2 つのセクションを参照することがあります。 1 つは sh_info セクションヘッダーエントリにより示されるシンボルテーブルで、もう 1 つは sh_link セクションヘッダーエントリにより示される変更対象のセクションです。「セクション」 に、各セクションの関係を示します。再配置オブジェクトに再配置セクションが存在するが、実行可能ファイルや共有オブジェクトがオプションの場合は、sh_info エントリが必要です。再配置オフセットが存在すれば、再配置を実行できます。
いずれの場合でも r_offset 値は、影響を受けるストレージユニットの先頭バイトのオフセットまたは仮想アドレスを指定します。再配置タイプは、変更されるビットと、これらのビットの値の計算方法を指定します。
再配置計算を記述するために次の表記が使用されます。
再配置可能フィールドの値を計算するために使用される加数。
実行時に共有オブジェクトがメモリーに読み込まれるベースアドレス。一般的に、共有オブジェクトファイルは、ベース仮想アドレス 0 で作成されます。ただし、共有オブジェクトの実行アドレスは異なります。「プログラムヘッダー」を参照してください。
実行時に再配置エントリのシンボルのアドレスが存在する大域オフセットテーブルへのオフセット。「大域オフセットテーブル (プロセッサ固有)」を参照してください。
大域オフセットテーブルのアドレス。「大域オフセットテーブル (プロセッサ固有)」を参照してください。
シンボルに対するプロシージャーのリンクテーブルエントリのセクションオフセットまたはアドレス。「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。
再配置されるストレージユニットのセクションオフセットまたはアドレス (r_offset を使用して計算)。
インデックスが再配置エントリ内に存在するシンボルの値。
インデックスが再配置エントリ内に存在するシンボルのサイズ。
SPARC プラットフォームでは、再配置エントリはバイト (byte8)、ハーフワード (half16)、ワード (word32)、および拡張ワード (xword64) に適用されます。
再配置フィールドの dispn ファミリ (disp19、disp22、disp30) は、ワード整列された符号拡張の PC 相対ディスプレイスメントです。すべてワードの位置 0 の最下位ビットで値をエンコードし、値に割り当てられたビット数についてのみ異なります。
d2/disp8 および d2/disp14 バリアントは、隣接しない 2 つのビットフィールド d2 および disp n を使用して、16 および 10 ビットのディスプレイスメント値をエンコードします。
再配置フィールドの immn ファミリ (imm5、imm6、imm7、imm10、imm13、imm22) は、符号なしの整数定数を表します。すべてワードの位置 0 の最下位ビットで値をエンコードし、値に割り当てられたビット数についてのみ異なります。
再配置フィールドの simmn ファミリ (simm10、simm11、simm13、simm22) は、符号付きの整数定数を表します。すべてワードの位置 0 の最下位ビットで値をエンコードし、値に割り当てられたビット数についてのみ異なります。
次の表に示すフィールド名は、再配置型がオーバーフローを検査するかどうかを通知します。計算される再配置値は意図したフィールドより大きい場合があり、再配置型によっては値の適合を検証 (V) したり結果を切り捨てたり (T) することがあります。たとえば、V-simm13 は、計算された値が simm13 フィールドの外部に 0 以外の有意ビットを持つことがないことを意味します。
表 12-14 SPARC: ELF 再配置型
|
いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。
R_SPARC_LO10 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、 R_SPARC_GOT10 は、大域オフセットテーブルの作成をリンカーに指示します。
R_SPARC_13 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、R_SPARC_GOT13 は、大域オフセットテーブルの作成をリンカーに指示します。
R_SPARC_22 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、R_SPARC_GOT22 は、大域オフセットテーブルの作成をリンカーに指示します。
R_SPARC_WDISP30 に似ていますが、シンボルのプロシージャーリンクテーブルエントリのアドレスを参照する点が異なります。また、R_SPARC_WPLT30 は、プロシージャーのリンクテーブル作成をリンカーに指示します。
リンカーは、この再配置型を作成して、動的実行可能ファイルが読み取り専用のテキストセグメントを保持できるようにします。この再配置型のオフセットメンバーは、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。「コピー再配置」を参照してください。
R_SPARC_32 に似ていますが、再配置は GOT エントリを指定されたシンボルのアドレスに設定する点が異なります。この特殊な再配置型を使うと、シンボルと GOT エントリの対応付けを判定できます。
リンカーは、動的オブジェクトが遅延結合を提供できるようにするため、この再配置型を作成します。この再配置型のオフセットメンバーは、プロシージャーのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャーのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。
リンカーは、動的オブジェクト用にこの再配置型を作成します。この再配置型のオフセットメンバーは、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスに相対アドレスを加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して値 0 を指定する必要があります。
R_SPARC_32 に似ていますが、整列されていないワードを参照する点が異なります。再配置されるワードは、任意整列が存在する 4 つの別個のバイトとして処理されなければなりません (アーキテクチャーの要求に従って整列されるワードとしては処理されません)。
R_SPARC_HI22 に似ていますが、妥当性検証ではなく切り捨てを行う点が異なります。
R_SPARC_PC22に似ていますが、妥当性検証ではなく切り捨てを行う点が異なります。
64 ビットアドレス空間の最上位 4G バイトに限定される実行可能ファイルに対して R_SPARC_LOX10 とともに使用されます。R_SPARC_HI22 に似ていますが、リンク値の 1 の補数を与えます。
R_SPARC_HIX22 とともに使用されます。R_SPARC_LO10 に似ていますが、必ずリンク値のビット 10 からビット 12 までを設定します。
再配置型 R_SPARC_H44 および R_SPARC_M44 とともに使用され、44 ビット絶対アドレス指定モデルを生成します。
レジスタシンボルの初期化に使用されます。この再配置型のオフセットメンバーには、初期化されるレジスタ番号が存在します。このレジスタに対応するレジスタシンボルが必要です。このシンボルの種類は SHN_ABS です。
これらの再配置はコード変換に対応したものです。
再配置計算に使用される次の表記は、64 ビット SPARC 固有のものです。
再配置可能フィールドの値を計算するために使用される二次的な加数。この加数は、ELF64_R_TYPE_DATA マクロを適用することにより r_info フィールドから抽出されます。
次の表に示す再配置型は、32 ビット SPARC 用に定義された再配置型を拡張または変 更します。「SPARC: 再配置型」を参照してください。
表 12-15 64 ビット SPARC: ELF 再配置型
|
次の再配置型には、単純な計算を超えたセマンティクスが存在します。
R_SPARC_LO10 に似ていますが、符号付き13 ビット即値フィールドを十分に使用するために余分なオフセットが追加される点が異なります。
x86 では、再配置エントリはワード (word32) および拡張ワード (xword64) に適用されます。
word32 は、任意バイト整列が存在する 4 バイトを占める 32 ビットフィールドを指定します。これらの値は、x86 アーキテクチャーにおけるほかのワード値と同じバイト順序を使用します。
次の表に、32 ビット x86 用に定義された再配置を示します。
表 12-16 32 ビット x86: ELF 再配置型
|
いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。
GOT のベースからシンボルの GOT エントリまでの距離を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
シンボルのプロシージャーのリンクテーブルエントリのアドレスを計算し、かつプロシージャーのリンクテーブルを作成するようにリンカーに指示します。
リンカーは、この再配置型を作成して、動的実行可能ファイルが読み取り専用のテキストセグメントを保持できるようにします。この再配置型のオフセットメンバーは、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。「コピー再配置」を参照してください。
GOT エントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと GOT エントリの対応付けを判定できます。
リンカーは、動的オブジェクトが遅延結合を提供できるようにするため、この再配置型を作成します。この再配置型のオフセットメンバーは、プロシージャーのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャーのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。
リンカーは、動的オブジェクト用にこの再配置型を作成します。この再配置型のオフセットメンバーは、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスに相対アドレスを加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して値 0 を指定する必要があります。
シンボルの値と GOT のアドレスの差を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
R_386_PC32 に似ていますが、計算を行う際に GOT のアドレスを使用する点が異なります。この再配置で参照されるシンボルは、通常 _GLOBAL_OFFSET_TABLE_ です。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
次の表に、x64 用に定義された再配置を示します。
表 12-17 x64: ELF 再配置型
|
これらの再配置型のほとんどの特別なセマンティクスは、x86 で使用されているものと同じです。いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。
この再配置のセマンティクスは R_AMD64_GOT32 または等しい R_386_GOTPC 再配置と異なります。x64 アーキテクチャーは、命令ポインタに対して相対的なアドレス指定モードを提供します。したがって、アドレスは 1 つの命令で GOT から読み込むことができます。
R_AMD64_GOTPCREL 再配置の計算は、シンボルのアドレスを指定した GOT 内の位置と再配置を適用する位置の間の差を提供します。
計算値は 32 ビットに切り捨てられます。リンカーは、再配置のために生成された値が元の 64 ビット値にゼロ拡張されていることを確認します。
計算値は 32 ビットに切り捨てられます。リンカーは、再配置のために生成された値が元の 64 ビット値に符号拡張されていることを確認します。
これらの再配置は x64 ABI には準拠していませんが、ドキュメント化するためにここに追加しておきます。R_AMD64_8 再配置は、計算値を 8 ビットに切り詰めます。R_AMD64_16 再配置は、計算値を 16 ビットに切り詰めます。