リンカーとライブラリ

x86: Local Dynamic (LD)

このコードシーケンスは、共有オブジェクトまたは動的実行可能ファイルで使用できます。このシーケンスは、参照として同じオブジェクト内に結合された TLS 変数を参照する場合に使用します。動的な tlsoffset はリンク編集時に結合が可能なため、___tls_get_addr() の呼び出しは、LD コードシーケンスを介して参照されるすべてのシンボルの関数呼び出しごとに 1 回だけですみます。

表 8–9 x86: Local Dynamic スレッド固有変数のアクセスコード

コードシーケンス 

初期の再配置 

シンボル 

0x00 leal  x1@tlsldm(%ebx), %eax
0x06 call  x@tlsldmplt
R_386_TLS_LDM
R_386_TLS_LDM_PLT
x1
x1
# %eax - 現在のオブジェクトの TLS ブロックのアドレスが含まれる
 
0x10 leal x1@dtpoff(%eax), %edx
R_386_TLS_LDO_32
x1
# %edx - ローカル TLS 変数 x1 のアドレスが含まれる
 
0x20 leal x2@dtpoff(%eax), %edx
R_386_TLS_LDO_32
x2
# %edx - ローカル TLS 変数 x2 のアドレスが含まれる
 
 

未処理の再配置 

シンボル 

GOT[n]
GOT[n + 1]
R_386_TLS_DTPMOD32
<なし>
x

最初の leal 命令は R_386_TLS_LDM 再配置を生成します。この再配置は、現在のオブジェクトの TLS_index 構造体を保持する領域を大域オフセットテーブル内に割り当てるよう、リンカーに指示します。リンカーは、この新しいリンクテーブルエントリに GOT からの相対オフセットを代入することによって、この再配置を処理します。

読み込みオブジェクトインデックスは実行時まで認識されないため、R_386_TLS_DTPMOD32 再配置が作成され、構造体の ti_tlsoffset フィールドにゼロが埋め込まれます。call 命令には、R_386_TLS_LDM_PLT 再配置によってタグが付けられます。

各ローカルシンボルの TLS オフセットはリンク編集時に認識されるため、リンカーはこれらの値を直接埋め込みます。

手続きが複数のローカルシンボルを参照する場合には、コンパイラは TLS ブロックの基底アドレスを取得するコードを 1 度だけ生成します。以後、各シンボルのアドレスの計算にはこの基底アドレスが使用され、個別にライブラリを呼び出すことはありません。