SPARC: スレッド固有変数へのアクセス
SPARC では、スレッド固有変数へのアクセスに次のコードシーケンスモデルを使用できます。
SPARC: General Dynamic (GD)
このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。
表 14-2 SPARC: General Dynamic スレッド固有変数のアクセスコードコードシーケンス
| 初期の再配置
| シンボル
|
# %l7 - initialized to GOT pointer
0x00 sethi %hi(@dtlndx(x)), %o0
0x04 add %o0, %lo(@dtlndx(x)), %o0
0x08 add %l7, %o0, %o0
0x0c call x@TLSPLT
# %o0 - contains address of TLS variable
|
R_SPARC_TLS_GD_HI22
R_SPARC_TLS_GD_LO10
R_SPARC_TLS_GD_ADD
R_SPARC_TLS_GD_CALL
|
x
x
x
x
|
| 未処理の再配置: 32 ビット
| シンボル
|
GOT[n]
GOT[n + 1]
| R_SPARC_TLS_DTPMOD32
R_SPARC_TLS_DTPOFF32
| x
x
|
| 未処理の再配置: 64 ビット
| シンボル
|
GOT[n]
GOT[n + 1]
| R_SPARC_TLS_DTPMOD64
R_SPARC_TLS_DTPOFF64
| x
x
|
|
sethi 命令は R_SPARC_TLS_GD_HI22 再配置を生成し、add 命令は R_SPARC_TLS_GD_LO10 再配置を生成します。これらの再配置は、変数 x の TLS_index 構造体を保持する領域を GOT 内に割り当てるように、リンカーに指示します。リンカーは、この新しい GOT エントリに GOT からの相対オフセットを代入することによって、この再配置を処理します。
読み込みオブジェクトインデックスと x の TLS ブロックインデックスは実行時まで不明です。したがって、リンカーは、実行時リンカーによって処理されるように、GOT に対する R_SPARC_TLS_DTPMOD32 再配置と R_SPARC_TLS_DPTOFF32 再配置を設定します。
2 番目の add 命令は、R_SPARC_TLS_GD_ADD 再配置を生成します。この再配置が使用されるのは、リンカーによって GD コードシーケンスがほかのシーケンスに変更される場合だけです。
call 命令は特別な構文である x@TLSPLT を使用します。この call 命令は TLS 変数を参照し、R_SPARC_TLS_GD_CALL 再配置を生成します。この再配置は、__tls_get_addr() 関数の呼び出しを結合するようリンカーに指示し、call 命令を GD コードシーケンスに関連付けます。
注 - add 命令は、
call 命令の前に指定する必要があります。
add 命令を、呼び出しの遅延スロットに配置することはできません。これは、あとで発生するコード変換が既知の順序を必要とするためです。
R_SPARC_TLS_GD_ADD 再配置によってタグが付けられた add 命令の GOT ポインタとして使用されるレジスタは、add 命令内の最初のレジスタでなければなりません。このように指定することで、リンカーはコード変換時に GOT ポインタであるレジスタを識別できるようになります。
SPARC: Local Dynamic (LD)
このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。
表 14-3 SPARC: Local Dynamic スレッド固有変数のアクセスコードコードシーケンス
| 初期の再配置
| シンボル
|
# %l7 - initialized to GOT pointer
0x00 sethi %hi(@tmndx(x1)), %o0
0x04 add %o0, %lo(@tmndx(x1)), %o0
0x08 add %l7, %o0, %o0
0x0c call x@TLSPLT
# %o0 - contains address of TLS block of current object
0x10 sethi %hi(@dtpoff(x1)), %l1
0x14 xor %l1, %lo(@dtpoff(x1)), %l1
0x18 add %o0, %l1, %l1
# %l1 - contains address of local TLS variable x1
0x20 sethi %hi(@dtpoff(x2)), %l2
0x24 xor %l2, %lo(@dtpoff(x2)), %l2
0x28 add %o0, %l2, %l2
# %l2 - contains address of local TLS variable x2
|
R_SPARC_TLS_LDM_HI22
R_SPARC_TLS_LDM_LO10
R_SPARC_TLS_LDM_ADD
R_SPARC_TLS_LDM_CALL
R_SPARC_TLS_LDO_HIX22
R_SPARC_TLS_LDO_LOX10
R_SPARC_TLS_LDO_ADD
R_SPARC_TLS_LDO_HIX22
R_SPARC_TLS_LDO_LOX10
R_SPARC_TLS_LDO_ADD
|
x1
x1
x1
x1
x1
x1
x1
x2
x2
x2
|
| 未処理の再配置: 32 ビット
| シンボル
|
GOT[n]
GOT[n + 1]
| R_SPARC_TLS_DTPMOD32
<none>
| x1
|
| 未処理の再配置: 64 ビット
| シンボル
|
GOT[n]
GOT[n + 1]
| R_SPARC_TLS_DTPMOD64
<none>
| x1
|
|
最初の sethi 命令は R_SPARC_TLS_LDM_HI22 再配置を生成し、add 命令は R_SPARC_TLS_LDM_LO10 再配置を生成します。これらの再配置は、現在のオブジェクトの TLS_index 構造体を保持する領域を GOT に割り当てるように、リンカーに指示します。リンカーは、この新しい GOT エントリに GOT からの相対オフセットを代入することによって、この再配置を処理します。
読み込みオブジェクトインデックスは実行時まで不明です。したがって、R_SPARC_TLS_DTPMOD32 再配置が作成され、TLS_index 構造体の ti_tlsoffset フィールドにゼロが埋め込まれます。
2 つめの add 命令には R_SPARC_TLS_LDM_ADD 再配置によってタグが付けられ、call 命令には R_SPARC_TLS_LDM_CALL 再配置によってタグが付けられます。
以降の sethi 命令は R_SPARC_LDO_HIX22 再配置を生成し、xor 命令は R_SPARC_TLS_LDO_LOX10 再配置を生成します。各局所シンボルの TLS オフセットはリンク編集時に認識されるため、これらの値は直接埋め込まれます。add 命令には、R_SPARC_TLS_LDO_ADD 再配置によってタグが付けられます。
手続きが複数の局所シンボルを参照する場合には、コンパイラは TLS ブロックの基底アドレスを取得するコードを 1 度だけ生成します。以後、各シンボルのアドレスの計算にはこの基底アドレスが使用され、個別にライブラリを呼び出すことはありません。
注 - R_SPARC_TLS_LDO_ADD によってタグが付けられた add 命令内の TLS オブジェクトアドレスが入ったレジスタは、命令シーケンス内の最初のレジスタでなければなりません。このように指定することで、リンカーはコード変換時にレジスタを識別できるようになります。
32-bit SPARC: Initial Executable (IE)
このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。
表 14-4 32-bit SPARC: Initial Executable スレッド固有変数のアクセスコードコードシーケンス
| 初期の再配置
| シンボル
|
# %l7 - initialized to GOT pointer, %g7 - thread pointer
0x00 sethi %hi(@tpoff(x)), %o0
0x04 or %o0, %lo(@tpoff(x)), %o0
0x08 ld [%l7 + %o0], %o0
0x0c add %g7, %o0, %o0
# %o0 - contains address of TLS variable
|
R_SPARC_TLS_IE_HI22
R_SPARC_TLS_IE_LO10
R_SPARC_TLS_IE_LD
R_SPARC_TLS_IE_ADD
|
x
x
x
x
|
| 未処理の再配置
| シンボル
|
GOT[n]
| R_SPARC_TLS_TPOFF32
| x
|
|
sethi 命令は R_SPARC_TLS_IE_HI22 再配置を生成し、or 命令は R_SPARC_TLS_IE_LO10 再配置を生成します。これらの再配置は、シンボル x の静的な TLS オフセットを保存する領域を GOT 内に作成するように、リンカーに指示します。実行時リンカーがシンボル x の負の静的 TLS オフセットを埋め込むよう、GOT に対する R_SPARC_TLS_TPOFF32 の再配置は、未処理の状態に置かれます。ld 命令には R_SPARC_TLS_IE_LD 再配置によってタグが付けられ、add 命令には R_SPARC_TLS_IE_ADD 再配置によってタグが付けられます。
注 - R_SPARC_TLS_IE_ADD 再配置によってタグが付けられた add 命令の GOT ポインタとして使用されるレジスタは、この命令内の最初のレジスタでなければなりません。このように指定することで、リンカーはコード変換時に GOT ポインタであるレジスタを識別できるようになります。
64-bit SPARC: Initial Executable (IE)
このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。
表 14-5 64-bit SPARC: Initial Executable スレッド固有変数のアクセスコードコードシーケンス
| 初期の再配置
| シンボル
|
# %l7 - initialized to GOT pointer, %g7 - thread pointer
0x00 sethi %hi(@tpoff(x)), %o0
0x04 or %o0, %lo(@tpoff(x)), %o0
0x08 ldx [%l7 + %o0], %o0
0x0c add %g7, %o0, %o0
# %o0 - contains address of TLS variable
|
R_SPARC_TLS_IE_HI22
R_SPARC_TLS_IE_LO10
R_SPARC_TLS_IE_LD
R_SPARC_TLS_IE_ADD
|
x
x
x
x
|
| 未処理の再配置
| シンボル
|
GOT[n]
| R_SPARC_TLS_TPOFF64
| x
|
|
SPARC: Local Executable (LE)
このコードシーケンスは、Thread-Local Storage Access Modelsで説明されている スレッド固有ストレージのアクセスモデル モデルを実装します。
表 14-6 SPARC: Local Executable スレッド固有変数のアクセスコードコードシーケンス
| 初期の再配置
| シンボル
|
# %g7 - thread pointer
0x00 sethi %hix(@tpoff(x)), %o0
0x04 xor %o0,%lo(@tpoff(x)),%o0
0x08 add %g7, %o0, %o0
# %o0 - contains address of TLS variable
|
R_SPARC_TLS_LE_HIX22
R_SPARC_TLS_LE_LOX10
<none>
|
x
x
|
|
sethi 命令は R_SPARC_TLS_LE_HIX22 再配置を生成し、xor 命令は R_SPARC_TLS_LE_LOX10 再配置を生成します。リンカーは、実行可能ファイルで定義されたシンボルの静的な TLS オフセットに、これらの再配置を直接結合します。実行時には、再配置処理は不要です。