リンカーとライブラリ

x86: Initial Executable (IE)

IE モデルには 2 つのコードシーケンスが存在します。その 1 つは、GOT ポインタを使用する、位置に依存しないコード用です。もう 1 つのシーケンスは、GOT ポインタを使用しない、位置に依存するコード用です。どちらのコードシーケンスも、動的実行可能ファイルでのみ使用できます。これらのコードシーケンスは、その実行可能ファイル内、またはプロセスの起動時に読み込まれる任意の共有ライブラリ内で定義された TLS 変数を参照できます。このモデルは、プロセスの起動後に読み込まれる共有ライブラリ内の TLS 変数を参照することはできません。

表 8–10 x86: 位置に依存しない Initial Executable スレッド固有変数のアクセスコード

コードシーケンス 

初期の再配置 

シンボル 

0x00 movl  %gs:0, %eax
0x06 addl  x@gotntpoff(%ebx), %eax

# %eax - TLS 変数のアドレスが含まれる
<なし>
R_386_TLS_GOTIE
 
x
 

未処理の再配置 

シンボル 

GOT[n]
R_386_TLS_TPOFF
x

addl 命令は R_386_TLS_GOTIE 再配置を生成します。この再配置は、シンボル x の静的な TLS オフセットを保存する領域を大域オフセットテーブル内に作成するよう、リンカーに指示します。このとき、GOT テーブルに対する R_386_TLS_TPOFF 再配置は、未処理の状態に置かれます。あとで、実行時リンカーがシンボル x の静的な TLS オフセットを埋め込みます。

表 8–11 x86: 位置に依存する Initial Executable スレッド固有変数のアクセスコード

コードシーケンス 

初期の再配置 

シンボル 

0x00 movl  %gs:0, %eax
0x06 addl  x@indntpoff, %eax

# %eax - TLS 変数のアドレスが含まれる
<なし>
R_386_TLS_IE
 
x
 

未処理の再配置 

シンボル 

GOT[n]
R_386_TLS_TPOFF
x

addl 命令は R_386_TLS_IE 再配置を生成します。この再配置は、シンボル x の静的な TLS オフセットを保存する領域を大域オフセットテーブル内に作成するよう、リンカーに指示します。このシーケンスと位置に依存しない形式との主な違いは、GOT ポインタレジスタのオフセットを介してではなく、作成される GOT エントリに直接、命令が結合されることです。このとき、GOT に対する R_386_TLS_TPOFF 再配置は、未処理の状態に置かれます。あとで、実行時リンカーがシンボル x の静的な TLS オフセットを埋め込みます。

次の 2 つのシーケンスに示すように、メモリー参照にオフセットを直接埋め込むことによって、変数 x の (アドレスではなく) 内容を読み込むことができます。

表 8–12 x86: 位置に依存しない Initial Executable 動的スレッド固有変数のアクセスコード

コードシーケンス 

初期の再配置 

シンボル 

0x00 movl  x@gotntpoff(%ebx), %eax
0x06 movl  %gs:(%eax), %eax

# %eax - TLS 変数のアドレスが含まれる
R_386_TLS_GOTIE
<なし>
x
 

未処理の再配置 

シンボル 

GOT[n]
R_386_TLS_TPOFF
x

表 8–13 x86: 位置に依存しない Initial Executable スレッド固有変数のアクセスコード

コードシーケンス 

初期の再配置 

シンボル 

0x00 movl  x@indntpoff, %ecx
0x06 movl  %gs:(%ecx), %eax

# %eax - TLS 変数のアドレスが含まれる
R_386_TLS_IE
<なし>
x
 

未処理の再配置 

シンボル 

GOT[n]
R_386_TLS_TPOFF
x

最後のシーケンスで、上記の %ecx ではなく %eax レジスタを使用すると、最初の命令は 5 バイト長または 6 バイト長になる可能性があります。