Oracle® Solaris 11.2 リンカーとライブラリガイド

印刷ビューの終了

更新: 2014 年 7 月
 
 

x64: スレッド固有変数へのアクセス

x64 では、TLS へのアクセスに次のコードシーケンスモデルを使用できます。

x64: General Dynamic (GD)

このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。

表 14-18  x64: General Dynamic スレッド固有変数のアクセスコード
コードシーケンス
初期の再配置
シンボル
0x00 .byte 0x66
0x01 leaq  x@tlsgd(%rip), %rdi
0x08 .word 0x6666
0x0a rex64
0x0b call  __tls_get_addr@plt

# %rax - contains address of TLS variable
<none>
R_AMD64_TLSGD
<none>
<none>
R_AMD64_PLT32
x


__tls_get_addr
未処理の再配置
シンボル
GOT[n]
GOT[n + 1]
R_AMD64_DTPMOD64
R_AMD64_DTPOFF64
x
x

__tls_get_addr() 関数は、tls_index 構造体のアドレスという 1 つのパラメータを取ります。x@tlsgd(%rip) による式と関連付けられた R_AMD64_TLSGD 再配置は、tls_index 構造体を GOT 内で割り当てるように、リンカーに指示します。tls_index 構造体で必要な 2 つの要素は、連続する GOT エントリである GOT[n] および GOT[n+1] で保持されます。これらの GOT エントリは、R_AMD64_DTPMOD64 再配置と R_AMD64_DTPOFF64 再配置に関連付けられます。

アドレス 0x00 の命令は、最初の GOT エントリのアドレスを計算します。この計算により、リンク編集時に明らかになる GOT の最初の PC 相対アドレスが現在の命令のポインタに追加されます。結果は、%rdi レジスタを使用して __tls_get_addr() 関数に渡されます。


注 - leaq 命令は、最初の GOT エントリのアドレスを計算します。この計算は、リンク編集時に決定された GOT の PC 相対アドレスを現在の命令のポインタに追加して行われます。.byte.word、および .rex64 接頭辞によって、命令シーケンス全体で 16 バイトを占めることが確実になります。接頭辞が使用されるのは、コードに悪影響を及ぼすことがないからです。

x64: Local Dynamic (LD)

このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。

表 14-19  x64: Local Dynamic スレッド固有変数のアクセスコード
コードシーケンス
初期の再配置
シンボル
0x00 leaq  x1@tlsld(%rip), %rdi
0x07 call  __tls_get_addr@plt

# %rax - contains address of TLS block

0x10 leaq  x1@dtpoff(%rax), %rcx

# %rcx - contains address of TLS variable x1

0x20 leaq  x2@dtpoff(%rax), %r9

# %r9 - contains address of TLS variable x2
R_AMD64_TLSLD
R_AMD64_PLT32



R_AMD64_DTOFF32



R_AMD64_DTOFF32
x1
__tls_get_addr




x1



x2
未処理の再配置
シンボル
GOT[n]
R_AMD64_DTMOD64
x1

最初の 2 つの命令は、パッドはありませんが、一般的な動的モデルに使用されるコードシーケンスと同じです。2 つの命令は必ず連続させてください。x1@tlsld(%rip) シーケンスは、シンボル x1tls_index エントリを生成します。このインデックスはオフセットがゼロ の x1 を含む現在のモジュールを参照します。リンカーは、オブジェクト R_AMD64_DTMOD64 の再配置を作成します。

オフセットは別々に読み込まれるので、R_AMD64_DTOFF32 再配置は不要です。x1@dtpoff による式は、シンボル x1 のオフセットにアクセスするために使用されます。この命令をアドレス 0x10 として使用して、完全なオフセットが読み込まれ %rax() 内の __tls_get_addr 呼び出しの結果に追加されて結果が %rcx に生成されます。x1@dtpoff による式は、R_AMD64_DTPOFF32 再配置を作成します。

次の命令を使用すると、変数のアドレスを計算するのではなく、変数の値を読み込むことができます。この命令は、元の leaq 命令と同じ再配置を作成します。

movq  x1@dtpoff(%rax), %r11

TLS ブロックのベースアドレスがレジスタ内で保持されていると、保護されているスレッド固有変数のアドレスの読み込み、保存、または計算には 1 つの命令が必要となります。

固有の動的モデルを使用した場合には、一般的な動的モデルを使用した場合よりも利点があります。すべての追加スレッド固有変数アクセスに必要なのは、3 つの新しい命令だけです。さらに、GOT エントリの追加や実行時の再配置は必要ありません。

x64: Initial Executable (IE)

このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。

表 14-20  x64: Initial Executable スレッド固有変数のアクセスコード
コードシーケンス
初期の再配置
シンボル
0x00 movq  %fs:0, %rax
0x09 addq  x@gottpoff(%rip), %rax

# %rax - contains address of TLS variable
<none>
R_AMD64_GOTTPOFF
x
未処理の再配置
シンボル
GOT[n]
R_AMD64_TPOFF64
x

シンボル xR_AMD64_GOTTPOFF 再配置は、リンカーに GOT エントリおよび関連する R_AMD64_TPOFF64 再配置の生成を要求します。その後、この命令は x@gottpoff(%rip) 命令の最後からの GOT エントリの相対オフセットを使用します。R_AMD64_TPOFF64 再配置は、現在ロードされているモジュールから決定されるシンボル x の値を使用します。オフセットは GOT エントリに書き込まれたあとで、addq 命令によってロードされます。

x のアドレスではなく x の内容を読み込む場合は、次のシーケンスを使用できます。

表 14-21  x64: Initial Executable スレッド固有変数のアクセスコード II
コードシーケンス
初期の再配置
シンボル
0x00 movq  x@gottpoff(%rip), %rax
0x07 movq  %fs:(%rax), %rax

# %rax - contains contents of TLS variable
R_AMD64_GOTTPOFF
<none>
x
未処理の再配置
シンボル
GOT[n]
R_AMD64_TPOFF64
x

x64: Local Executable (LE)

このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。

表 14-22  x64: Local Executable スレッド固有変数のアクセスコード
コードシーケンス
初期の再配置
シンボル
0x00 movq  %fs:0, %rax
0x09 leaq  x@tpoff(%rax), %rax

# %rax - contains address of TLS variable
<none>
R_AMD64_TPOFF32
x

TLS 変数のアドレスではなく TLS 変数の内容を読み込む場合は、次のシーケンスを使用できます。

表 14-23  x64: Local Executable スレッド固有変数のアクセスコード II
コードシーケンス
初期の再配置
シンボル
0x00 movq  %fs:0, %rax
0x09 movq  x@tpoff(%rax), %rax

# %rax - contains contents of TLS variable
<none>
R_AMD64_TPOFF32
x

次のシーケンスはより短いものです。

表 14-24  x64: Local Executable スレッド固有変数のアクセスコード III
コードシーケンス
初期の再配置
シンボル
0x00 movq  %fs:x@tpoff, %rax

# %rax - contains contents of TLS variable
R_AMD64_TPOFF32
x