リンカーとライブラリ

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

SPARC では、スレッド固有変数へのアクセスに次のコードシーケンスモデルを使用できます。

SPARC: General Dynamic (GD)

このコードシーケンスは、「スレッド固有領域のアクセスモデル」で説明されている GD モデルを実装します。

表 8–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 再配置を生成します。これらの再配置は、変数 xTLS_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)

このコードシーケンスは、「スレッド固有領域のアクセスモデル」で説明されている LD モデルを実装します。

表 8–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 ビット SPARC: Initial Executable (IE)

このコードシーケンスは、「スレッド固有領域のアクセスモデル」で説明されている IE モデルを実装します。

表 8–4 32 ビット 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 ビット SPARC: Initial Executable (IE)

このコードシーケンスは、「スレッド固有領域のアクセスモデル」で説明されている IE モデルを実装します。

表 8–5 64 ビット 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)

このコードシーケンスは、「スレッド固有領域のアクセスモデル」で説明されている LE モデルを実装します。

表 8–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 オフセットに、これらの再配置を直接結合します。実行時には、再配置処理は不要です。