リンカーとライブラリ

SPARC: 64 ビットプロシージャのリンクテーブル

64 ビット SPARC 動的オブジェクトの場合、プロシージャのリンクテーブルは専用データ内に存在します。実行時リンカーは、宛先の絶対アドレスを判定し、これらの絶対アドレスに従ってプロシージャのリンクテーブルのメモリーイメージに変更を加えます。

最初の 4 つのプロシージャのリンクテーブルエントリは、予約されています。表 7–49 で例示されてはいますが、これらのエントリの元の内容は指定されていません。テーブル内の先頭 32,768 エントリは、それぞれ 8 ワード (32 バイト) を占め、32 バイト境界で整列する必要があります。テーブル全体は 256 バイト境界で整列する必要があります。32,768 を超えるエントリが必要な場合、残りのエントリは 6 ワード (24 バイト) および 1 つのポインタ (8 バイト) で構成されます。 命令は、160 エントリのブロックにまとめられ、その次に 160 個ポインタが続きます。最後のグループのエントリとポインタは、160 未満でもかまいません。パディングの必要はありません。


注 –

32,768 および 160 という数字は、それぞれ分岐と読み込み置換の制限に基づいており、また、キャッシュの効率を向上させるために、コードとデータの間の区分を 256 バイト境界に合わせています。


再配置テーブルは、プロシージャのリンクテーブルに関連付けられています。_DYNAMIC 配列の DT_JMP_REL エントリは、最初の再配置エントリの位置を与えます。再配置テーブルには、予約されていないプロシージャのリンクテーブルエントリごとに 1 つのエントリが同じ順番で存在します。各エントリの再配置タイプは、R_SPARC_JMP_SLOT です。最初の 32,767 スロットでは、再配置オフセットは関連するプロシージャのリンクテーブルエントリの先頭バイトのアドレスを指定します。加数フィールドはゼロになります。シンボルテーブルインデックスは適切なシンボルを参照します。32,768 以後のスロットでは、再配置オフセットは関連するポインタの先頭バイトのアドレスを指定します。加数フィールドは、再配置されていない値 -(.PLTN + 4) になります。シンボルテーブルインデックスは適切なシンボルを参照します。

プロシージャのリンクテーブルの機能を説明するため、表 7–49 にエントリがいくつか示されています。最初の 3 つのエントリは、予約済みの初期エントリを示します。続く 3 つのエントリは、32,768 エントリの初期状態と、それぞれ、対象アドレスがエントリの +/- 2G バイト以内の場合、アドレス空間の下位 4G バイト以内の場合、およびその他の場合に適用されると考えられる、変換された状態を示しています。最後の 2 つのエントリは、命令とポインタのペアで構成される、後のエントリの例を示します。左欄は、動的リンクが行われる前のオブジェクトファイルの命令を示しています。右欄は、実行時リンカーがプロシージャのリンクテーブルエントリを変更した結果を示しています。

表 7–49 64-bit SPARC: プロシージャのリンクテーブルの例
オブジェクトファイルメモリーセグメント
.PLT0:
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
.PLT1:
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
    unimp
.PLT2:
    unimp
.PLT0:
    save    %sp, -176, %sp
    sethi   %hh(runtime_linker_0), %l0
    sethi   %lm(runtime_linker_0), %l1
    or      %l0, %hm(runtime_linker_0), %l0
    sllx    %l0, 32, %l0
    or      %l0, %l1, %l0
    jmpl    %l0+%lo(runtime_linker_0), %o1
    mov     %g1, %o0
.PLT1:
    save    %sp, -176, %sp
    sethi   %hh(runtime_linker_1), %l0
    sethi   %lm(runtime_linker_1), %l1
    or      %l0, %hm(runtime_linker_1), %l0
    sllx    %l0, 32, %l0
    or      %l0, %l1, %l0
    jmpl    %l0+%lo(runtime_linker_0), %o1
    mov     %g1, %o0
.PLT2:
    .xword  identification
.PLT101:
    sethi   (.-.PLT0), %g1
    ba,a    %xcc, .PLT1
    nop
    nop
    nop;    nop
    nop;    nop
.PLT102:
    sethi   (.-.PLT0), %g1
    ba,a    %xcc, .PLT1
    nop
    nop
    nop;    nop
    nop;    nop
.PLT103:
    sethi   (.-.PLT0),  %g1
    ba,a    %xcc, .PLT1
    nop
    nop
    nop
    nop
    nop
    nop
.PLT101:
    nop
    mov     %o7,  %g1
    call    name101
    mov     %g1, %o7
    nop;    nop
    nop;    nop
.PLT102:
    nop
    sethi   %hi(name102), %g1
    jmpl    %g1+%lo(name102), %g0
    nop
    nop;    nop
    nop;    nop
.PLT103:
    nop
    sethi   %hh(name103), %g1
    sethi   %lm(name103), %g5
    or      %hm(name103), %g1
    sllx    %g1, 32, %g1
    or      %g1, %g5, %g5
    jmpl    %g5+%lo(name103), %g0
    nop
.PLT32768:
    mov     %o7, %g5
    call    .+8
    nop
    ldx     [%o7+.PLTP32768 -
              (.PLT32768+4)], %g1
    jmpl    %o7+%g1, %g1
    mov     %g5, %o7

    ...

.PLT32927:
    mov     %o7, %g5
    call    .+8
    nop
    ldx     [%o7+.PLTP32927 -
              (.PLT32927+4)], %g1
    jmpl    %o7+%g1, %g1
    mov     %g5, %o7
.PLT32768:
    <unchanged>
    <unchanged>
    <unchanged>
    <unchanged>

    <unchanged>
    <unchanged>

    ...

.PLT32927:
    <unchanged>
    <unchanged>
    <unchanged>
    <unchanged>

    <unchanged>
    <unchanged>
.PLTP32768
    .xword  .PLT0 -
              (.PLT32768+4)
    ...

.PLTP32927
    .xword  .PLT0 -
              (.PLT32927+4)
.PLTP32768
    .xword  name32768 -
              (.PLT32768+4)
    ...
    
.PLTP32927
    .xword  name32927 -
	      (.PLT32927+4)

実行時リンカーとプログラムは、以下の手順に従ってプロシージャのリンクテーブル内のシンボル参照を協調して解決します。ただし、以下に記述されている手順は、単に説明用のためのものです。実行時リンカーの正確な実行時動作については、記述されていません。

  1. 実行時リンカーは、プログラムのメモリーイメージを最初に作成するとき、プロシージャのリンクテーブルの初期エントリに、実行時リンカー自身のルーチンの 1 つに制御を渡すように変更を加える。実行時リンカーはまた、識別情報 (identification) の拡張ワードを 3 番目のエントリに格納する。実行時リンカーは、制御を受け取ると、この拡張ワードを調べることで、このルーチンを呼び出したオブジェクトを見つけることができる

  2. 他のすべてのプロシージャのリンクテーブルエントリは、最初、先頭または 2 番目のエントリに渡される。これらのエントリは、スタックフレームを確立して、実行時リンカーを呼び出す

  3. 実行時リンカーは、識別情報の値を使うことによってオブジェクトのデータ構造体 (再配置テーブルを含む) を取得する

  4. 実行時リンカーは、テーブルスロットの再配置エントリのインデックスを計算する

  5. インデックス情報に関しては、実行時リンカーはシンボルの実際の値を取得し、スタックを戻し、プロシージャのリンクテーブルエントリを変更してから、制御を宛先に渡す

実行時リンカーは、メモリーセグメント欄に示された命令シーケンスを必ずしも作成する必要はありません。ただし、作成する場合は、いくつかの点でより詳細な説明が必要です。

エントリの 2 番目のフォームに示すように、ポインタの変更は、単一の不可分 64 ビットストアを使用して行われます。


注 –

.PLT101.PLT102、および .PLT103 の命令シーケンスの違いから、関連する宛先に合わせた最適化の方法を知ることができます。


LD_BIND_NOW 環境変数は、動的リンク動作を変更します。この環境変数の値がヌル文字列以外の場合、実行時リンカーは、プログラムに制御を渡す前に R_SPARC_JMP_SLOT 再配置エントリ (プロシージャのリンクテーブルエントリ) を処理します。