JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
リンカーとライブラリ     Oracle Solaris 10 8/11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

1.  Oracle Solaris リンカーの紹介

2.  リンカー

3.  実行時リンカー

4.  共有オブジェクト

5.  アプリケーションバイナリインタフェースとバージョン管理

6.  サポートインタフェース

7.  オブジェクトファイル形式

ファイル形式

データ表現

ELF ヘッダー

ELF 識別

データの符号化

セクション

セクションのマージ

特殊セクション

「COMDAT」セクション

グループセクション

機能セクション

ハッシュテーブルセクション

移動セクション

注釈セクション

再配置セクション

再配置型 (プロセッサ固有)

SPARC: 再配置型

64 ビット SPARC: 再配置型

32 ビット x86: 再配置型

x64: 再配置型

文字列テーブルセクション

シンボルテーブルセクション

シンボル値

シンボルテーブルのレイアウトと規則

シンボルソートセクション

レジスタシンボル

Syminfo テーブルセクション

バージョン管理セクション

バージョン定義セクション

バージョン依存セクション

バージョンシンボルセクション

動的リンク

プログラムヘッダー

ベースアドレス

セグメントへのアクセス権

セグメントの内容

プログラムの読み込み (プロセッサ固有)

プログラムインタプリタ

実行時リンカー

動的セクション

大域オフセットテーブル (プロセッサ固有)

プロシージャーのリンクテーブル (プロセッサ固有)

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

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

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

x64: プロシージャーのリンクテーブル

8.  スレッド固有領域 (TLS)

9.  mapfile

A.  リンカーのクイックリファレンス

B.  バージョン管理の手引き

C.  動的ストリングトークンによる依存関係の確立

D.  直接結合

E.  System V Release 4 (バージョン 1) Mapfile

F.  リンカーとライブラリのアップデートおよび新機能

索引

動的リンク

このセクションは、オブジェクトファイル情報と、プログラムの実行イメージを作成するシステム動作を記述します。ここで説明する情報の大半は、すべてのシステムに適用されます。プロセッサに固有の情報はその旨が示されたセクションに存在します。

実行可能オブジェクトファイルと共有オブジェクトファイルは、アプリケーションプログラムを静的に表現します。このようなプログラムを実行するためには、システムはこれらのファイルを使用して動的なプログラムの表現、すなわちプロセスイメージを作成します。プロセスイメージには、テキスト、データ、スタックなどがあるセグメントが存在します。次の主な細目があります。

プログラムヘッダー

実行可能オブジェクトファイルまたは共有オブジェクトファイルのプログラムヘッダーテーブルは、構造体の配列です。各構造体は、実行されるプログラムを準備するためにシステムが必要とするセグメントなどの情報を記述します。各オブジェクトファイルセグメントには、「セグメントの内容」で説明しているように、1 つ以上のセクションが存在します。

プログラムヘッダーは、実行可能オブジェクトファイルと共有オブジェクトファイルに対してのみ意味があります。プログラムヘッダーサイズは、ELF ヘッダーの e_phentsize メンバーと e_phnum メンバーで指定されます。

プログラムヘッダーの構造体は、次のとおりです。sys/elf.h を参照してください。

typedef struct {
        Elf32_Word      p_type;
        Elf32_Off       p_offset;
        Elf32_Addr      p_vaddr;
        Elf32_Addr      p_paddr;
        Elf32_Word      p_filesz;
        Elf32_Word      p_memsz;
        Elf32_Word      p_flags;
        Elf32_Word      p_align;
} Elf32_Phdr;

typedef struct {
        Elf64_Word      p_type;
        Elf64_Word      p_flags;
        Elf64_Off       p_offset;
        Elf64_Addr      p_vaddr;
        Elf64_Addr      p_paddr;
        Elf64_Xword     p_filesz;
        Elf64_Xword     p_memsz;
        Elf64_Xword     p_align;
} Elf64_Phdr;
p_type

この配列要素が記述するセグメント型、または配列要素情報の解釈方法。型の値とその意味は、表 7-25 を参照してください。

p_offset

ファイルの先頭から、セグメントの先頭バイトが存在する位置までのオフセット。

p_vaddr

セグメントの先頭バイトが存在するメモリー内の仮想アドレス。

p_paddr

セグメントの物理アドレス (物理アドレス指定が適切なシステムの場合)。本システムはアプリケーションプログラムに対して物理アドレス指定を無視するので、このメンバーには実行可能ファイルと共有オブジェクトに対する指定されていない内容が存在します。

p_filesz

セグメントのファイルイメージのバイト数 (0 の場合もある)。

p_memsz

セグメントのメモリーイメージのバイト数 (0 の場合もある)。

p_flags

セグメントに関係するフラグ。型の値とその意味は、表 7-26 を参照してください。

p_align

読み込み可能なプロセスセグメントは、ページサイズを基にして、p_vaddrp_offset に対して同じ値を保持する必要があります。このメンバーは、セグメントがメモリーとファイルにおいて整列される値を与えます。値 01 は、整列が必要ないことを意味します。その他の値の場合、p_align2 の正整数累乗でなければならず、また p_vaddrp_align を法として p_offset に等しくなければなりません。「プログラムの読み込み (プロセッサ固有)」を参照してください。

エントリの中には、プロセスセグメントを記述するものもあります。それ以外のエントリは補足情報を与え、プロセスイメージには関与しません。セグメントエントリが現れる順序は、明示されている場合を除き任意です。定義されている型の値を、次の表に示します。

表 7-25 ELF セグメント型

名前
PT_NULL
0
PT_LOAD
1
PT_DYNAMIC
2
PT_INTERP
3
PT_NOTE
4
PT_SHLIB
5
PT_PHDR
6
PT_TLS
7
PT_LOOS
0x60000000
PT_SUNW_UNWIND
0x6464e550
PT_SUNW_EH_FRAME
0x6474e550
PT_LOSUNW
0x6ffffffa
PT_SUNWBSS
0x6ffffffa
PT_SUNWSTACK
0x6ffffffb
PT_SUNWDTRACE
0x6ffffffc
PT_SUNWCAP
0x6ffffffd
PT_HISUNW
0x6fffffff
PT_HIOS
0x6fffffff
PT_LOPROC
0x70000000
PT_HIPROC
0x7fffffff
PT_NULL

未使用メンバーの値は不定です。この型を使用すると、プログラムヘッダーテーブルに、無視されるエントリを入れることができます。

PT_LOAD

p_fileszp_memsz により記述される読み込み可能セグメントを指定します。ファイルのバイト列は、メモリーセグメントの先頭に対応付けられます。セグメントのメモリーサイズ (p_memsz) がファイルサイズ (p_filesz) より大きい場合、不足するバイトは、値 0 を保持するように定義されます。これらのバイトはセグメントの初期化領域に続きます。ファイルサイズがメモリーサイズより大きくなることは許可されません。プログラムヘッダーテーブルの読み込み可能セグメントエントリは昇順に現れ、p_vaddr メンバーでソートされます。

PT_DYNAMIC

動的リンクに関する情報を指定します。「動的セクション」を参照してください。

PT_INTERP

インタプリタとして呼び出される、ヌル文字で終了しているパス名の位置とサイズを指定します。動的実行可能ファイルの場合、この型は必須です。共有オブジェクトの場合は、この型を指定することができます。この型は、ファイル内で複数指定することはできません。この型が存在する場合、この型はすべての読み込み可能セグメントエントリの前に存在しなければなりません。詳細は、「プログラムインタプリタ」を参照してください。

PT_NOTE

補助情報の位置とサイズを指定します。詳細は、「注釈セクション」を参照してください。

PT_SHLIB

このセグメント型は、予約済みですが、セマンティクスは定義されていません。

PT_PHDR

プログラムヘッダーテーブルの、ファイル、およびプログラムのメモリーイメージにおける位置とサイズを指定します。このセグメント型を、ファイル内に複数指定することはできません。また、このセグメント型は、プログラムヘッダーテーブルがプログラムのメモリーイメージの一部になる場合にかぎり指定できます。この型が存在する場合、この型はすべての読み込み可能セグメントエントリの前に存在しなければなりません。詳細は、「プログラムインタプリタ」を参照してください。

PT_TLS

スレッド固有領域のテンプレートを指定します。詳細は、「スレッド固有領域 (TLS) セクション」を参照してください。

PT_LOOS - PT_HIOS

この範囲の値 (両端の値を含む) は、OS 固有のセマンティクスのために予約されています。

PT_SUNW_UNWIND

このセグメントは、スタック巻き戻し (unwind) テーブルを含んでいます。

PT_SUNW_EH_FRAME

このセグメントは、スタック巻き戻し (unwind) テーブルを含んでいます。PT_SUNW_EH_FRAMEPT_SUNW_EH_UNWIND に相当します。

PT_LOSUNW - PT_HISUNW

この範囲の値 (両端の値を含む) は、Sun 固有のセマンティクスのために予約されています。

PT_SUNWBSS

PT_LOAD 要素と同じ属性で、.SUNW_bss セクションの記述に使用します。

PT_SUNWSTACK

プロセススタックを記述します。PT_SUNWSTACK 要素は 1 つのみ存在できます。p_flags フィールドで定義されたアクセス権のみが意味を持ちます。

PT_SUNWDTRACE

dtrace(1M) の内部使用のため予約されています。

PT_SUNWCAP

機能要件を指定します。詳細については、「機能セクション」を参照してください。

PT_LOPROC - PT_HIPROC

この範囲の値 (両端の値を含む) は、プロセッサ固有のセマンティクスのために予約されています。


注 - ほかの箇所で特に要求されないかぎり、すべてのプログラムヘッダーセグメントタイプはそれぞれ存在することもありますし、存在しないこともあります。ファイルのプログラムヘッダーテーブルには、このプログラムの内容に関係する要素のみが存在できます。


ベースアドレス

実行可能オブジェクトファイルと共有オブジェクトファイルには、ベースアドレス (プログラムのオブジェクトファイルのメモリーイメージに関連付けられている最下位仮想アドレス) が存在します。ベースアドレスは、たとえば動的リンク時にプログラムのメモリーイメージを再配置するために使用されます。

実行可能オブジェクトファイルと共有オブジェクトファイルのベースアドレスは、実行時に 3 つの値 (プログラムの読み込み可能セグメントのメモリー読み込みアドレス、最大ページサイズ、最下位仮想アドレス) から計算されます。プログラムヘッダーの仮想アドレスは、プログラムのメモリーイメージの実際の仮想アドレスを表さないことがあります。「プログラムの読み込み (プロセッサ固有)」を参照してください。

ベースアドレスを計算するには、PT_LOAD セグメントの最下位 p_vaddr 値に関連付けられているメモリーアドレスを判定します。次に、メモリーアドレスを最大ページサイズの最近倍数に切り捨てることで、ベースアドレスが求められます。メモリーに読み込まれるファイルの型によって、メモリーアドレスは p_vaddr 値に一致しない場合もあります。

セグメントへのアクセス権

システムで読み込まれるプログラムには、少なくとも 1 つの読み込み可能セグメントが存在しなければなりません (ただし、この制限はファイル形式による要件ではありません)。システムは、読み込み可能セグメントのメモリーイメージを作成するとき、p_flags メンバーで指定されるアクセス権を与えます。PF_MASKPROC マスクのすべてのビットは、プロセッサ固有のセマンティクスのために予約されます。

表 7-26 ELF セグメントフラグ

名前
意味
PF_X
0x1
実行
PF_W
0x2
書き込み
PF_R
0x4
読み取り
PF_MASKPROC
0xf0000000
指定なし

アクセス権ビットが 0 の場合、そのビットのアクセスは拒否されます。実際のメモリーアクセス権は、メモリー管理ユニット (システムによって異なることがある) に依存します。すべてのフラグ組み合わせが有効ですが、システムは要求以上のアクセスを与えることがあります。ただしどんな場合も、特に断りが明示的に記述されていないかぎり、セグメントは書き込み権を持ちません。次の表に、正確なフラグ解釈と許容されるフラグ解釈を示します。

表 7-27 ELF セグメントへのアクセス権

フラグ
正確なフラグ解釈
許容されるフラグ解釈
None
0
すべてのアクセスが拒否される
すべてのアクセスが拒否される
PF_X
1
実行のみ
読み取り、実行
PF_W
2
書き込みのみ
読み取り、書き込み、実行
PF_W+PF_X
3
書き込み、実行
読み取り、書き込み、実行
PF_R
4
読み取りのみ
読み取り、実行
PF_R + PF_X
5
読み取り、実行
読み取り、実行
PF_R+PF_W
6
読み取り、書き込み
読み取り、書き込み、実行
PF_R + PF_W + PF_X
7
読み取り、書き込み、実行
読み取り、書き込み、実行

たとえば、標準的なテキストセグメントは読み取り権と実行権を持っていますが、書き込み権は持っていません。データセグメントは通常、読み取り権、書き込み権、および実行権を持っています。

セグメントの内容

オブジェクトファイルセグメントは、1 つまたは複数のセクションで構成されます。ただし、プログラムヘッダーはこの事実には関与しません。ファイルセグメントに 1 つのセクションが存在するか複数のセクションが存在するかもまた、プログラム読み込み時に重要ではありません。しかし、さまざまなデータが、プログラム実行時や動的リンク時などには存在しなければなりません。次に、セグメントの内容を一般的な言葉で説明します。セグメント内のセクションの順序と帰属関係は、異なることがあります。

テキストセグメントには、読み取り専用の命令/データが存在します。データセグメントには、書き込み可能のデータ/命令が存在します。すべての特殊セクションの一覧については、表 7-10 を参照してください。

PT_DYNAMIC プログラムヘッダー要素は、.dynamic セクションを指し示します。さらに、.got セクションと .plt セクションには、位置独立のコードと動的リンクに関係する情報が存在します。

.plt は、テキストセグメントまたはデータセグメントに存在できます (どちらのセグメントに存在するかはプロセッサに依存します)。詳細は、「大域オフセットテーブル (プロセッサ固有)」「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。

タイプ SHT_NOBITS のセクションは、ファイル内の領域を占有しませんが、セグメントのメモリーイメージには反映されます。通常、これらの初期化されていないデータはセグメントの終わりに存在し、その結果、関連付けられているプログラムヘッダー要素において p_memszp_filesz より大きくなります。

プログラムの読み込み (プロセッサ固有)

システムは、プロセスイメージを作成または拡張するとき、ファイルのセグメントを仮想メモリーセグメントに論理的にコピーします。システムがファイルをいつ物理的に読み取るかは、プログラムの挙動やシステムの負荷などに依存します。

プロセスは実行時に論理ページを参照しないかぎり物理ページを必要としません。プロセスは一般に多くのページを未参照状態のままにします。したがって、物理読み取りを遅延させると、システム性能を向上させることができます。この効率性を実現するには、実行可能ファイルと共有オブジェクトファイルには、ファイルオフセットと仮想アドレスがページサイズを法として同じであるセグメントイメージが存在する必要があります。

32 ビットのセグメントの仮想アドレスとファイルオフセットは、64K (0x10000) を法として同じです。64 ビットのセグメントの仮想アドレスとファイルオフセットは、1M バイト (0x100000) を法として同じです。セグメントを最大ページサイズに整列すると、ファイルは物理ページサイズには関係なくページング処理に対して適切になります。

デフォルトでは 64 ビット SPARC プログラムは開始アドレス (0x100000000) にリンクされます。プログラム全体は、テキスト、データ、ヒープ、スタック、および共用オブジェクト依存関係を含めて、4G バイトより上に存在します。そうすることにより、プログラムがポインタを切り捨てると、アドレス空間の最下位 4G バイトでフォルトが発生することになるので、64 ビットプログラムが正しいことをより簡単に確認できます。64 ビットプログラムは 4G バイトより上でリンクされていますが、リンカーに mapfile および -M オプションを使用することにより、プログラムを 4G バイト未満でリンクすることも可能です。詳細は、/usr/lib/ld/sparcv9/map.below4G を参照してください。

次の図に、SPARC バージョンの実行可能ファイルの例を示します。

図 7-8 SPARC: 実行可能ファイル (64K に整列)

image:SPARC 実行ファイルのレイアウト例

次の表に、前の図に示した読み込み可能セグメント要素の定義を示します。

表 7-28 SPARC: ELF プログラムヘッダーセグメント (64K に整列)

メンバー
テキスト
データ
p_type
PT_LOAD
PT_LOAD
p_offset
0x0
0x4000
p_vaddr
0x10000
0x24000
p_paddr
指定なし
指定なし
p_filesize
0x3a82
0x4f5
p_memsz
0x3a82
0x10a4
p_flags
PF_R + PF_X
PF_R + PF_W + PF_X
p_align
0x10000
0x10000

次の図に、x86 バージョンの実行可能ファイルの例を示します。

図 7-9 32 ビット x86: 実行可能ファイル (64K に整列)

image:x86 実行可能ファイルのレイアウトの例。

次の表に、前の図に示した読み込み可能セグメント要素の定義を示します。

表 7-29 32 ビット x86: ELF プログラムヘッダーセグメント (64K に整列)

メンバー
テキスト
データ
p_type
PT_LOAD
PT_LOAD
p_offset
0x0
0x4000
p_vaddr
0x8050000
0x8064000
p_paddr
指定なし
指定なし
p_filesize
0x32fd
0x3a0
p_memsz
0x32fd
0xdc4
p_flags
PF_R + PF_X
PF_R + PF_W + PF_X
p_align
0x10000
0x10000

例に示したファイルオフセットと仮想アドレスは、テキストとデータの両方に対して最大ページサイズを法として同じですが、最大 4 ファイルページ (ページサイズとファイルシステムブロックサイズに依存) に、純粋ではないテキストやデータが含まれます。


注 - 前の例は、テキストセグメントを丸めた、典型的な Oracle Solaris OS のバイナリを反映したものです。


データセグメントの終わりは、初期化されていないデータに対して特別な処理を必要とします (初期値が 0 になるようにシステムで定義されている)。ファイルの最後のデータページに、論理メモリーページに存在しない情報が存在する場合、これらのデータは 0 に設定しなければなりません (実行可能ファイルの未知の内容のままにしてはならない)。

ほかの 3 ページに含まれる純粋でないテキストまたはデータは、論理的にはプロセスイメージの一部ではありません。システムがこれらの純粋でないテキストまたはデータを除去するかどうかについては、規定されていません。このプログラムのメモリーイメージが 4K バイト (0x1000) ページを使用する例を、次の図に示します。単純化するために次の図では、1 ページのサイズのみを示しています。

図 7-10 32 ビット SPARC: プロセスイメージセグメント

image:SPARC プロセスイメージセグメントの例

図 7-11 x86: プロセスイメージセグメント

image:x86 プロセスイメージセグメントの例

セグメント読み込みは、実行可能ファイルと共有オブジェクトでは異なる側面が 1 つ存在します。実行可能ファイルのセグメントには、標準的には絶対コードが存在します。プロセスを正しく実行するには、セグメントは実行可能ファイルを作成するために使用された仮想アドレスに存在しなければなりません。システムは変化しない p_vaddr 値を仮想アドレスとして使用します。

一方、通常は共有オブジェクトのセグメントには、位置独立のコードが存在します。したがって、セグメントの仮想アドレスは、実行動作を無効にすることなくプロセス間で変化させることができます。

システムは個々のプロセスごとに仮想アドレスを選択しますが、セグメントの相対位置は維持します。位置独立のコードはセグメント間で相対アドレス指定を使用するので、メモリーの仮想アドレス間の差は、ファイルの仮想アドレス間の差に一致しなければなりません。

次の表は、いくつかのプロセスに対する共有オブジェクト仮想アドレスの割り当ての例で、一定の相対位置になることを示しています。これらの表は、ベースアドレスの計算も示しています。

表 7-30 32 ビット SPARC: ELF 共有オブジェクトセグメントアドレスの例

送信元
テキスト
データ
ベースアドレス
ファイル
0x0
0x4000
0x0
プロセス 1
0xc0000000
0xc0024000
0xc0000000
プロセス 2
0xc0010000
0xc0034000
0xc0010000
プロセス 3
0xd0020000
0xd0024000
0xd0020000
プロセス 4
0xd0030000
0xd0034000
0xd0030000

表 7-31 32 ビット x86: ELF 共有オブジェクトセグメントアドレスの例

送信元
テキスト
データ
ベースアドレス
ファイル
0x0
0x4000
0x0
プロセス 1
0x8000000
0x8004000
0x80000000
プロセス 2
0x80081000
0x80085000
0x80081000
プロセス 3
0x900c0000
0x900c4000
0x900c0000
プロセス 4
0x900c6000
0x900ca000
0x900c6000

プログラムインタプリタ

動的リンクを開始する動的実行可能ファイルまたは共有オブジェクトは、1 つの PT_INTERP プログラムヘッダー要素を保持できます。システムは exec(2) の実行中に、PT_INTERP セグメントからパス名を取り出し、そのインタプリタファイルのセグメントから初期プロセスイメージを作成します。インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を提供する必要があります。

Oracle Solaris OS では、インタプリタは実行時リンカー ld.so.1(1) として知られています。

実行時リンカー

リンカーは、動的リンクを開始する動的オブジェクトを作成する際、PT_INTERP 型のプログラムヘッダー要素を実行可能ファイルに付加します。この要素は、実行時リンカーをプログラムインタプリタとして呼び出すようにシステムに指示します。exec(2) と実行時リンカーは、協調してプログラムのプロセスイメージを作成します。

リンカーはまた、実行時リンカーを支援する、実行可能ファイルと共有オブジェクトファイル用のさまざまなデータを作成します。これらのデータは読み込み可能セグメントに存在するため、データを実行時に使用できます。これらのセグメントには、次のものが含まれます。

共有オブジェクトは、ファイルのプログラムヘッダーテーブルに記録されているアドレスとは異なる仮想メモリーアドレスを占有することが可能です。実行時リンカーは、アプリケーションが制御を取得する前に、メモリーイメージを再配置して絶対アドレスを更新します。

動的セクション

オブジェクトファイルが動的リンクに関係している場合、このオブジェクトファイルのプログラムヘッダーテーブルには、PT_DYNAMIC 型の要素が存在します。このセグメントには、.dynamic セクションが存在します。特殊なシンボル _DYNAMIC は、このセクションを示し、このセクションには、次の構造体を持つ配列が存在します。sys/link.h を参照してください。

typedef struct {
        Elf32_Sword d_tag;
        union {
                Elf32_Word      d_val;
                Elf32_Addr      d_ptr;
                Elf32_Off       d_off;
        } d_un;
} Elf32_Dyn;

typedef struct {
        Elf64_Xword d_tag;
        union {
                Elf64_Xword     d_val;
                Elf64_Addr      d_ptr;
        } d_un;
} Elf64_Dyn;

このタイプの各オブジェクトの場合、d_tagd_un の解釈に影響します。

d_val

このオブジェクトは、さまざまに解釈される整数値を表します。

d_ptr

このオブジェクトは、プログラムの仮想アドレスを表します。ファイルの仮想アドレスは、実行時にメモリーの仮想アドレスに一致しないことがあります。実行時リンカーは、動的構造体に存在するアドレスを解釈するとき、元のファイル値とメモリーのベースアドレスに基づいて実際のアドレスを計算します。整合性のため、ファイルには動的構造体内のアドレスを「補正」するための再配置エントリは存在しません。

一般的に、各動的タグ値によって d_un union の解釈が決まります。この規則は、他社製ツールによる動的タグの解釈をよりシンプルにします。偶数の値を持つタグは、d_ptr を使用する動的セクションのエントリを示します。奇数の値を持つタグは、d_val を使用する動的セクションのエントリ、または d_ptrd_val のどちらも使用しない動的セクションのエントリを示します。互換性のために次のような特別な範囲の値を持つタグは、これらの規則に従いません。他社製ツールは、これらの例外的な範囲に項目ごとに明示的に対応する必要があります。

次の表は、実行可能オブジェクトファイルと共有オブジェクトファイルのタグ要求についてまとめています。タグに「必須」という印が付いている場合、動的リンク配列にはその型のエントリが存在しなければなりません。また、「任意」は、タグのエントリが現れてもよいですが必須ではないことを意味します。

表 7-32 ELF 動的配列タグ

名前
d_un
実行可能ファイル
共有オブジェクトファイル
DT_NULL
0
無視される
必須
必須
DT_NEEDED
1
d_val
任意
任意
DT_PLTRELSZ
2
d_val
任意
任意
DT_PLTGOT
3
d_ptr
任意
任意
DT_HASH
4
d_ptr
必須
必須
DT_STRTAB
5
d_ptr
必須
必須
DT_SYMTAB
6
d_ptr
必須
必須
DT_RELA
7
d_ptr
必須
任意
DT_RELASZ
8
d_val
必須
任意
DT_RELAENT
9
d_val
必須
任意
DT_STRSZ
10
d_val
必須
必須
DT_SYMENT
11
d_val
必須
必須
DT_INIT
12
d_ptr
任意
任意
DT_FINI
13
d_ptr
任意
任意
DT_SONAME
14
d_val
無視される
任意
DT_RPATH
15
d_val
任意
任意
DT_SYMBOLIC
16
無視される
無視される
任意
DT_REL
17
d_ptr
必須
任意
DT_RELSZ
18
d_val
必須
任意
DT_RELENT
19
d_val
必須
任意
DT_PLTREL
20
d_val
任意
任意
DT_DEBUG
21
d_ptr
任意
無視される
DT_TEXTREL
22
無視される
任意
任意
DT_JMPREL
23
d_ptr
任意
任意
DT_BIND_NOW
24
無視される
任意
任意
DT_INIT_ARRAY
25
d_ptr
任意
任意
DT_FINI_ARRAY
26
d_ptr
任意
任意
DT_INIT_ARRAYSZ
27
d_val
任意
任意
DT_FINI_ARRAYSZ
28
d_val
任意
任意
DT_RUNPATH
29
d_val
任意
任意
DT_FLAGS
30
d_val
任意
任意
DT_ENCODING
32
指定なし
指定なし
指定なし
DT_PREINIT_ARRAY
32
d_ptr
任意
無視される
DT_PREINIT_ARRAYSZ
33
d_val
任意
無視される
DT_MAXPOSTAGS
34
指定なし
指定なし
指定なし
DT_LOOS
0x6000000d
指定なし
指定なし
指定なし
DT_SUNW_AUXILIARY
0x6000000d
d_ptr
指定なし
任意
DT_SUNW_RTLDINF
0x6000000e
d_ptr
任意
任意
DT_SUNW_FILTER
0x6000000e
d_ptr
指定なし
任意
DT_SUNW_CAP
0x60000010
d_ptr
任意
任意
DT_SUNW_SYMTAB
0x60000011
d_ptr
任意
任意
DT_SUNW_SYMSZ
0x60000012
d_val
任意
任意
DT_SUNW_ENCODING
0x60000013
指定なし
指定なし
指定なし
DT_SUNW_SORTENT
0x60000013
d_val
任意
任意
DT_SUNW_SYMSORT
0x60000014
d_ptr
任意
任意
DT_SUNW_SYMSORTSZ
0x60000015
d_val
任意
任意
DT_SUNW_TLSSORT
0x60000016
d_ptr
任意
任意
DT_SUNW_TLSSORTSZ
0x60000017
d_val
任意
任意
DT_SUNW_CAPINFO
0x60000018
d_ptr
任意
任意
DT_SUNW_STRPAD
0x60000019
d_val
任意
任意
DT_SUNW_CAPCHAIN
0x6000001a
d_ptr
任意
任意
DT_SUNW_LDMACH
0x6000001b
d_val
任意
任意
DT_SUNW_CAPCHAINENT
0x6000001d
d_val
任意
任意
DT_SUNW_CAPCHAINSZ
0x6000001f
d_val
任意
任意
DT_HIOS
0x6ffff000
指定なし
指定なし
指定なし
DT_VALRNGLO
0x6ffffd00
指定なし
指定なし
指定なし
DT_CHECKSUM
0x6ffffdf8
d_val
任意
任意
DT_PLTPADSZ
0x6ffffdf9
d_val
任意
任意
DT_MOVEENT
0x6ffffdfa
d_val
任意
任意
DT_MOVESZ
0x6ffffdfb
d_val
任意
任意
DT_POSFLAG_1
0x6ffffdfd
d_val
任意
任意
DT_SYMINSZ
0x6ffffdfe
d_val
任意
任意
DT_SYMINENT
0x6ffffdff
d_val
任意
任意
DT_VALRNGHI
0x6ffffdff
指定なし
指定なし
指定なし
DT_ADDRRNGLO
0x6ffffe00
指定なし
指定なし
指定なし
DT_CONFIG
0x6ffffefa
d_ptr
任意
任意
DT_DEPAUDIT
0x6ffffefb
d_ptr
任意
任意
DT_AUDIT
0x6ffffefc
d_ptr
任意
任意
DT_PLTPAD
0x6ffffefd
d_ptr
任意
任意
DT_MOVETAB
0x6ffffefe
d_ptr
任意
任意
DT_SYMINFO
0x6ffffeff
d_ptr
任意
任意
DT_ADDRRNGHI
0x6ffffeff
指定なし
指定なし
指定なし
DT_RELACOUNT
0x6ffffff9
d_val
任意
任意
DT_RELCOUNT
0x6ffffffa
d_val
任意
任意
DT_FLAGS_1
0x6ffffffb
d_val
任意
任意
DT_VERDEF
0x6ffffffc
d_ptr
任意
任意
DT_VERDEFNUM
0x6ffffffd
d_val
任意
任意
DT_VERNEED
0x6ffffffe
d_ptr
任意
任意
DT_VERNEEDNUM
0x6fffffff
d_val
任意
任意
DT_LOPROC
0x70000000
指定なし
指定なし
指定なし
DT_SPARC_REGISTER
0x70000001
d_val
任意
任意
DT_AUXILIARY
0x7ffffffd
d_val
指定なし
任意
DT_USED
0x7ffffffe
d_val
任意
任意
DT_FILTER
0x7fffffff
d_val
指定なし
任意
DT_HIPROC
0x7fffffff
指定なし
指定なし
指定なし
DT_NULL

_DYNAMIC 配列の終わりを示します。

DT_NEEDED

ヌル文字で終わっている文字列の DT_STRTAB 文字列テーブルオフセットであり、必要な依存性の名前を示します。動的配列には、この型の複数のエントリが存在できます。これらのエントリの相対順序は意味がありますが、ほかの型のエントリに対するこれらのエントリの相対順序には意味がありません。「共有オブジェクトの依存性」を参照してください。

DT_PLTRELSZ

プロシージャーのリンクテーブルに関連付けられている再配置エントリの合計サイズ (単位: バイト)。「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。

DT_PLTGOT

プロシージャーのリンクテーブルまたは大域オフセットテーブルに関連付けられるアドレス。「プロシージャーのリンクテーブル (プロセッサ固有)」「大域オフセットテーブル (プロセッサ固有)」を参照してください。

DT_HASH

シンボルハッシュテーブルのアドレス。このテーブルは、DT_SYMTAB 要素で示されるシンボルテーブルを参照します。「ハッシュテーブルセクション」を参照してください。

DT_STRTAB

文字列テーブルのアドレス。文字列テーブルには、実行時リンカーが必要とするシンボル名、依存性名、およびほかの文字列が存在します。「文字列テーブルセクション」を参照してください。

DT_SYMTAB

シンボルテーブルのアドレス。「シンボルテーブルセクション」を参照してください。

DT_RELA

再配置テーブルのアドレス。「再配置セクション」を参照してください。

オブジェクトファイルには、複数の再配置セクションを指定できます。リンカーは、実行可能オブジェクトファイルまたは共有オブジェクトファイルの再配置テーブルを作成するとき、これらのセクションを連結して単一のテーブルを作成します。これらの各セクションはオブジェクトファイル内で独立している場合がありますが、実行時リンカーは単一のテーブルとして扱います。実行時リンカーは、実行可能ファイルのプロセスイメージを作成したり、またはプロセスイメージに共有オブジェクトを付加したりするとき、再配置テーブルを読み取り、関連付けられている動作を実行します。

この要素が存在する場合、DT_RELASZ 要素と DT_RELAENT 要素も存在する必要があります。再配置がファイルに対して必須の場合、DT_RELA または DT_REL が使用可能です。

DT_RELASZ

DT_RELA 再配置テーブルの合計サイズ (単位: バイト)。

DT_RELAENT

DT_RELA 再配置エントリのサイズ (単位: バイト)。

DT_STRSZ

DT_STRTAB 文字列テーブルの合計サイズ (単位: バイト)。

DT_SYMENT

DT_SYMTAB シンボルエントリのサイズ (単位: バイト)。

DT_INIT

初期化関数のアドレス。「初期設定および終了セクション」を参照してください。

DT_FINI

終了関数のアドレス。「初期設定および終了セクション」を参照してください。

DT_SONAME

ヌル文字で終わっている文字列の DT_STRTAB 文字列テーブルオフセットで、共有オブジェクトの名前を示します。「共有オブジェクト名の記録」を参照してください。

DT_RPATH

ヌル文字で終わっているライブラリ検索パス文字列の DT_STRTAB 文字列テーブルオフセット。この要素の使用は、DT_RUNPATH に置き換えられました。「実行時リンカーが検索するディレクトリ」を参照してください。

DT_SYMBOLIC

オブジェクトが、リンク編集中に適用されたシンボリック結合を含むことを示します。この要素の使用は、DF_SYMBOLIC フラグに置き換えられました。-B symbolic オプションの使用」を参照してください。

DT_REL

DT_RELA に似ていますが、テーブルに暗黙の加数が存在する点が異なります。この要素が存在する場合、DT_RELSZ 要素と DT_RELENT 要素も存在する必要があります。

DT_RELSZ

DT_REL 再配置テーブルの合計サイズ (単位: バイト)。

DT_RELENT

DT_REL 再配置エントリのサイズ (単位: バイト)。

DT_PLTREL

プロシージャーのリンクテーブルが参照する再配置エントリの型 (DT_REL または DT_RELA) を示します。1 つのプロシージャーのリンクテーブルでは、すべての再配置は、同じ再配置を使用しなければなりません。「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。この要素が存在する場合、DT_JMPREL 要素も存在する必要があります。

DT_DEBUG

デバッグに使用されます。

DT_TEXTREL

1 つまたは複数の再配置エントリが書き込み不可セグメントに対する変更を要求する可能性があり、実行時リンカーはそれに応じて対応できることを示します。この要素の使用は、DF_TEXTREL フラグに置き換えられました。「位置独立のコード」を参照してください。

DT_JMPREL

プロシージャーのリンクテーブルにのみ関連付けられている再配置エントリのアドレス。「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。これらの再配置エントリを分離しておくと、遅延結合が有効なオブジェクトの読み込み時に、実行時リンカーはこれらのエントリを無視できます。この要素が存在する場合、DT_PLTRELSZ 要素と DT_PLTREL 要素も存在する必要があります。

DT_POSFLAG_1

直後の DT_ 要素に適用されるさまざまな状態フラグ。表 7-35 を参照してください。

DT_BIND_NOW

プログラムに制御を渡す前に、このオブジェクトについてのすべての再配置を処理するよう実行時リンカーに指示します。環境または dlopen(3C) で指定された場合、このエントリは遅延結合の使用指令よりも優先されます。この要素の使用は、DF_BIND_NOW フラグに置き換えられました。詳細は、「再配置が実行されるとき」を参照してください。

DT_INIT_ARRAY

初期設定関数へのポインタの配列のアドレス。この要素が存在する場合、DT_INIT_ARRAYSZ 要素も存在する必要があります。「初期設定および終了セクション」を参照してください。

DT_FINI_ARRAY

終了関数へのポインタの配列のアドレス。この要素が存在する場合、DT_FINI_ARRAYSZ 要素も存在する必要があります。「初期設定および終了セクション」を参照してください。

DT_INIT_ARRAYSZ

DT_INIT_ARRAY 配列の合計サイズ (単位: バイト)。

DT_FINI_ARRAYSZ

DT_FINI_ARRAY 配列の合計サイズ (単位: バイト)。

DT_RUNPATH

ヌル文字で終わっているライブラリ検索パス文字列の DT_STRTAB 文字列テーブルオフセット。「実行時リンカーが検索するディレクトリ」を参照してください。

DT_FLAGS

このオブジェクトに特有のフラグ値。表 7-33 を参照してください。

DT_ENCODING

DT_ENCODING と等しいかそれより大きく、かつ DT_LOOS と等しいかそれより小さい動的タグ値は、 d_un union の解釈の規則に従います。

DT_PREINIT_ARRAY

「初期設定前」関数へのポインタの配列のアドレス。この要素が存在する場合、DT_PREINIT_ARRAYSZ 要素も存在する必要があります。この配列は、実行可能ファイル内でのみ処理されます。共有オブジェクト内に含まれている場合、この配列は無視されます。「初期設定および終了セクション」を参照してください。

DT_PREINIT_ARRAYSZ

DT_PREINIT_ARRAY 配列の合計サイズ (単位: バイト)。

DT_MAXPOSTAGS

値が正である動的配列タグの数。

DT_LOOS - DT_HIOS

この範囲の値 (両端の値を含む) は、オペレーティングシステム固有のセマンティクスのために予約されています。このような値はすべて、d_un union の解釈の規則に従います。

DT_SUNW_AUXILIARY

ヌル文字で終わっている文字列の DT_STRTAB 文字列テーブルオフセットで、シンボル別の補助フィルティーを 1 つ以上指定します。「補助フィルタの生成」を参照してください。

DT_SUNW_RTLDINF

実行時リンカーによる使用のために予約されています。

DT_SUNW_FILTER

ヌル文字で終わっている文字列の DT_STRTAB 文字列テーブルオフセットで、シンボル別の標準フィルティーを 1 つ以上指定します。「標準フィルタの生成」を参照してください。

DT_SUNW_CAP

機能セクションのアドレス。「機能セクション」を参照してください。

DT_SUNW_SYMTAB

シンボルテーブルのアドレス。局所関数シンボルが含まれ、DT_SYMTAB から提供されるシンボルを拡張します。これらのシンボルは常に、DT_SYMTAB から提供されるシンボルの直前に並んで配置されます。「シンボルテーブルセクション」を参照してください。

DT_SUNW_SYMSZ

DT_SUNW_SYMTABDT_SYMTAB から提供されるシンボルテーブルを結合したサイズ。

DT_SUNW_ENCODING

DT_SUNW_ENCODING と等しいかそれより大きく、かつ DT_HIOS と等しいかそれより小さい動的タグ値は、d_un union の解釈の規則に従います。

DT_SUNW_SORTENT

DT_SUNW_SYMSORT および DT_SUNW_TLSSORT シンボルソートエントリのサイズ (単位: バイト)。

DT_SUNW_SYMSORT

シンボルテーブルインデックスの配列のアドレス。DT_SUNW_SYMTAB が参照するシンボルテーブル内の関数シンボルと変数シンボルに、ソートキーに基づいてアクセスできます。「シンボルソートセクション」を参照してください。

DT_SUNW_SYMSORTSZ

DT_SUNW_SYMSORT 配列の合計サイズ (単位: バイト)。

DT_SUNW_TLSSORT

シンボルテーブルインデックスの配列のアドレス。DT_SUNW_SYMTAB が参照するシンボルテーブル内のスレッド固有シンボルに、ソートキーに基づいてアクセスできます。「シンボルソートセクション」を参照してください。

DT_SUNW_TLSSORTSZ

DT_SUNW_TLSSORT 配列の合計サイズ (単位: バイト)。

DT_SUNW_CAPINFO

シンボルをその機能要件に関連付けることができるシンボルテーブルインデックスの配列のアドレス。「機能セクション」を参照してください。

DT_SUNW_STRPAD

動的文字列テーブルの末尾に予約されている未使用領域の合計サイズ (単位: バイト)。オブジェクト内に DT_SUNW_STRPAD が存在しない場合は、予約されている領域はありません。

DT_SUNW_CAPCHAIN

機能ファミリインデックスの配列のアドレス。インデックスの各ファミリは 0 エントリで終了します。

DT_SUNW_LDMACH

このオブジェクトを生成したリンカーのマシンアーキテクチャー。DT_SUNW_LDMACH では、ELF ヘッダーの e_machine フィールドに使用される EM_ 整数値と同じ値が使用されます。「ELF ヘッダー」を参照してください。DT_SUNW_LDMACH は、オブジェクトを構築するリンカーのクラス (32 ビットまたは 64 ビット) とプラットフォームを識別するために使用されます。この情報は、実行時リンカーでは使用されず、ドキュメントのためだけに使用されます。

DT_SUNW_CAPCHAINENT

DT_SUNW_CAPCHAIN エントリのサイズ (バイト単位)。

DT_SUNW_CAPCHAINSZ

合計サイズ (バイト単位)、または DT_SUNW_CAPCHAIN 連鎖。

DT_SYMINFO

シンボル情報テーブルのアドレス。この要素が存在する場合、DT_SYMINENT 要素と DT_SYMINSZ 要素も存在する必要があります。「Syminfo テーブルセクション」を参照してください。

DT_SYMINENT

DT_SYMINFO 情報エントリのサイズ (単位: バイト)。

DT_SYMINSZ

DT_SYMINFO テーブルのサイズ (単位: バイト)。

DT_VERDEF

バージョン定義テーブルのアドレス。このテーブル内の要素には、文字列テーブル DT_STRTAB のインデックスが含まれます。この要素が存在する場合、DT_VERDEFNUM 要素も存在する必要があります。「バージョン定義セクション」を参照してください。

DT_VERDEFNUM

DT_VERDEF テーブルのエントリ数。

DT_VERNEED

バージョン依存性テーブルのアドレス。このテーブル内の要素には、文字列テーブル DT_STRTAB のインデックスが含まれます。この要素が存在する場合、DT_VERNEEDNUM 要素も存在する必要があります。「バージョン依存セクション」を参照してください。

DT_VERNEEDNUM

DT_VERNEEDNUM テーブルのエントリ数。

DT_RELACOUNT

すべての Elf32_Rela または Elf64_Rela 再配置の連結から生成される RELATIVE 再配置回数を示します。「再配置セクションの結合」を参照してください。

DT_RELCOUNT

すべての Elf32_Rel 再配置の連結から生成される RELATIVE 再配置回数を示します。「再配置セクションの結合」を参照してください。

DT_AUXILIARY

ヌル文字で終わっている DT_STRTAB 文字列テーブルオフセットで、1 つ以上の補助フィルティーを指定します。「補助フィルタの生成」を参照してください。

DT_FILTER

ヌル文字で終わっている DT_STRTAB 文字列テーブルオフセットで、1 つ以上の標準「フィルティー」を指定します。「標準フィルタの生成」を参照してください。

DT_CHECKSUM

オブジェクトの選択されたセクションの簡単なチェックサム。gelf_checksum(3ELF) のマニュアルページを参照してください。

DT_MOVEENT

DT_MOVETAB 移動エントリのサイズ (単位: バイト)。

DT_MOVESZ

DT_MOVETAB テーブルの合計サイズ (単位: バイト)。

DT_MOVETAB

移動テーブルのアドレス。この要素が存在する場合、DT_MOVEENT 要素と DT_MOVESZ 要素も存在する必要があります。「移動セクション」を参照してください。

DT_CONFIG

ヌル文字で終わっている DT_STRTAB 文字列テーブルオフセットで、構成ファイルを定義します。構成ファイルは、実行可能ファイルでのみ有効であり、通常このオブジェクトに固有のファイルです。「デフォルトの検索パスの設定」を参照してください。

DT_DEPAUDIT

ヌル文字で終わっている DT_STRTAB 文字列テーブルオフセットで、1 つ以上の監査ライブラリを定義します。「実行時リンカーの監査インタフェース」を参照してください。

DT_AUDIT

ヌル文字で終わっている DT_STRTAB 文字列テーブルオフセットで、1 つ以上の監査ライブラリを定義します。「実行時リンカーの監査インタフェース」を参照してください。

DT_FLAGS_1

このオブジェクトに特有のフラグ値。表 7-34 を参照してください。

DT_VALRNGLO - DT_VALRNGHI

この範囲の値 (両端の値を含む) は、動的構造体の d_un.d_val フィールドによって使用されます。

DT_ADDRRNGLO - DT_ADDRRNGHI

この範囲の値 (両端の値を含む) は、動的構造体の d_un.d_ptr フィールドによって使用されます。ELF オブジェクトが作成後に調整された場合、これらのエントリも更新する必要があります。

DT_SPARC_REGISTER

DT_SYMTAB シンボルテーブル内の STT_SPARC_REGISTER シンボルのインデックス。シンボルテーブルの各 STT_SPARC_REGISTER シンボルには、1 つの動的エントリが存在します。「レジスタシンボル」を参照してください。

DT_LOPROC - DT_HIPROC

この範囲の値は、プロセッサ固有のセマンティクスのために予約されています。

動的配列の最後にある DT_NULL 要素と、DT_NEEDEDDT_POSFLAG_1 要素の相対的な順序を除くと、エントリはどの順序で現れてもかまいません。表に示されていないタグ値は予約されています。

表 7-33 ELF 動的フラグ DT_FLAGS

名前
意味
DF_ORIGIN
0x1
$ORIGIN 処理が必要です
DF_SYMBOLIC
0x2
シンボリックシンボル解決が必要です
DF_TEXTREL
0x4
テキストの再配置が存在します
DF_BIND_NOW
0x8
非遅延結合が必要です
DF_STATIC_TLS
0x10
オブジェクトは静的なスレッド固有領域方式を使用します
DF_ORIGIN

オブジェクトに $ORIGIN 処理が必要であることを示します。「関連する依存関係の配置」を参照してください。

DF_SYMBOLIC

オブジェクトが、リンク編集中に適用されたシンボリック結合を含むことを示します。-B symbolic オプションの使用」を参照してください。

DF_TEXTREL

1 つまたは複数の再配置エントリが書き込み不可セグメントに対する変更を要求する可能性があり、実行時リンカーはそれに応じて対応できることを示します。「位置独立のコード」を参照してください。

DF_BIND_NOW

プログラムに制御を渡す前に、このオブジェクトについてのすべての再配置を処理するよう実行時リンカーに指示します。環境または dlopen(3C) で指定された場合、このエントリは遅延結合の使用指令よりも優先されます。詳細は、「再配置が実行されるとき」を参照してください。

DF_STATIC_TLS

静的なスレッド固有領域方式を使用するコードがオブジェクトに含まれていることを示します。静的なスレッド固有領域は、dlopen(3C) または遅延読み込みを使用して動的に読み込まれるオブジェクトでは使用すべきではありません。

表 7-34 ELF 動的フラグ DT_FLAGS_1

名前
意味
DF_1_NOW
0x1
完全な再配置処理を行います。
DF_1_GLOBAL
0x2
未使用
DF_1_GROUP
0x4
オブジェクトがグループのメンバーであることを示します。
DF_1_NODELETE
0x8
オブジェクトがプロセスから削除できないことを示します。
DF_1_LOADFLTR
0x10
フィルティーの即時読み込みを保証します。
DF_1_INITFIRST
0x20
オブジェクトの初期化を最初に実行します。
DF_1_NOOPEN
0x40
オブジェクトを dlopen(3C) で使用できません。
DF_1_ORIGIN
0x80
$ORIGIN 処理が必要です。
DF_1_DIRECT
0x100
直接結合が有効です。
DF_1_INTERPOSE
0x400
オブジェクトは割り込み処理です。
DF_1_NODEFLIB
0x800
デフォルトのライブラリ検索パスを無視します。
DF_1_NODUMP
0x1000
オブジェクトを dldump(3C) でダンプできません。
DF_1_CONFALT
0x2000
オブジェクトは代替構成です。
DF_1_ENDFILTEE
0x4000
「フィルティー」がフィルタの検索を終了します。
DF_1_DISPRELDNE
0x8000
ディスプレイスメント再配置が実行されました。
DF_1_DISPRELPND
0x10000
ディスプレイスメント再配置の保留。
DF_1_NODIRECT
0x20000
オブジェクトは間接的な結合を含みます。
DF_1_IGNMULDEF
0x40000
内部使用。
DF_1_NOKSYMS
0x80000
内部使用。
DF_1_NOHDR
0x100000
内部使用。
DF_1_EDITED
0x200000
オブジェクトが最初に構築されてから変更されています。
DF_1_NORELOC
0x400000
内部使用。
DF_1_SYMINTPOSE
0x800000
個別の割り込みシンボルが存在します。
DF_1_GLOBAUDIT
0x1000000
大域監査を確立します。
DF_1_SINGLETON
0x2000000
シングルトンシンボルが存在します。
DF_1_NOW

プログラムに制御を渡す前に、このオブジェクトについてのすべての再配置を処理するよう実行時リンカーに指示します。環境または dlopen(3C) で指定された場合、このフラグは遅延結合の使用指令よりも優先されます。詳細は、「再配置が実行されるとき」を参照してください。

DF_1_GROUP

オブジェクトがグループのメンバーであることを示します。このフラグは、リンカーの -B group オプションを使用してオブジェクトに記録されます。「オブジェクト階層」を参照してください。

DF_1_NODELETE

オブジェクトがプロセスから削除できないことを示します。オブジェクトは、dlopen(3C) で直接または依存性としてプロセスに読み込まれた場合、dlclose(3C) で読み込み解除できません。このフラグは、リンカーの -z nodelete オプションを使用してオブジェクトに記録されます。

DF_1_LOADFLTR

フィルタに対してのみ意味があります。関連付けられているすべてのフィルティーがただちに処理されることを示します。このフラグは、リンカーの -z loadfltr オプションを使用してオブジェクトに記録されます。「「フィルティー」の処理」を参照してください。

DF_1_INITFIRST

読み込まれたほかのオブジェクトよりも先に、このオブジェクトの初期化セクションが実行されることを示します。このフラグは特殊なシステムライブラリでのみ使用するもので、リンカーの -z initfirst オプションを使用してオブジェクトに記録されます。

DF_1_NOOPEN

dlopen(3C) を使ってオブジェクトを実行中のプロセスに追加できないことを示します。このフラグは、リンカーの -z nodlopen オプションを使用してオブジェクトに記録されます。

DF_1_ORIGIN

オブジェクトに $ORIGIN 処理が必要であることを示します。「関連する依存関係の配置」を参照してください。

DF_1_DIRECT

オブジェクトが直接結合情報を使用することを示します。付録 D 直接結合を参照してください。

DF_1_INTERPOSE

オブジェクトシンボルテーブルの割り込みが、一次読み込みオブジェクト (通常は実行可能ファイル) 以外のすべてのシンボルの前で発生します。このフラグは、リンカーの -z interpose オプションを使用して記録されます。「実行時割り込み」を参照してください。

DF_1_NODEFLIB

このオブジェクトの依存関係を検索する際、デフォルトのライブラリ検索パスがすべて無視されることを示します。このフラグは、リンカーの -z nodefaultlib オプションを使用してオブジェクトに記録されます。「実行時リンカーが検索するディレクトリ」を参照してください。

DF_1_NODUMP

このオブジェクトが dldump(3C) によってダンプされないことを示します。このオプションの候補には、再配置を保持しないオブジェクトが含まれ、これらのオブジェクトは、crle(1) を使用して代替オブジェクトを生成する際に含めることができます。このフラグは、リンカーの -z nodump オプションを使用してオブジェクトに記録されます。

DF_1_CONFALT

このオブジェクトが、crle(1) によって生成された代替構成オブジェクトであることを示します。このフラグにより実行時リンカーがトリガーされ、構成ファイル $ORIGIN/ld.config. app-name が検索されます。

DF_1_ENDFILTEE

「フィルティー」に対してのみ意味があります。以降の「フィルティー」に対するフィルタ検索は行われません。このフラグは、リンカーの -z endfiltee オプションを使用してオブジェクトに記録されます。「「フィルティー」検索の縮小」を参照してください。

DF_1_DISPRELDNE

このオブジェクトにディスプレイスメント再配置が適用されたことを示します。再配置が適用されるとレコードは破棄されるため、オブジェクト内のディスプレイスメント再配置レコードはもはや存在しません。「ディスプレイスメント再配置」を参照してください。

DF_1_DISPRELPND

このオブジェクトのディスプレイスメント再配置が保留されていることを示します。ディスプレイスメント再配置はオブジェクト内部で終了するため、再配置は実行時に完了できます。「ディスプレイスメント再配置」を参照してください。

DF_1_NODIRECT

このオブジェクトに、直接結合できないシンボルが含まれることを示します。「SYMBOL_SCOPE/SYMBOL_VERSION 指令」を参照してください。

DF_1_IGNMULDEF

カーネルの実行時リンカーによる使用のために予約されています。

DF_1_NOKSYMS

カーネルの実行時リンカーによる使用のために予約されています。

DF_1_NOHDR

カーネルの実行時リンカーによる使用のために予約されています。

DF_1_EDITED

このオブジェクトがリンカーによって最初に構築されたあとに編集または変更されたことを示します。このフラグは、オブジェクトが最初に構築されたあとになんらかの変更が加えられたことをデバッガに警告するために使用されます。

DF_1_NORELOC

カーネルの実行時リンカーによる使用のために予約されています。

DF_1_SYMINTPOSE

一次読み込みオブジェクト (通常は実行可能ファイル) 以外のすべてのシンボルの前に割り込むべき個々のシンボルが、オブジェクトに含まれることを示します。このフラグは、mapfileINTERPOSE キーワードを使ってオブジェクトが構築されるときに記録されます。「SYMBOL_SCOPE/SYMBOL_VERSION 指令」を参照してください。

DF_1_GLOBAUDIT

動的実行可能ファイルで大域監査が必要であることを示します。「大域監査の記録」を参照してください。

DF_1_SINGLETON

このオブジェクトに singleton シンボルが定義されている、またはオブジェクトがこのシンボルを参照していることを示します。「SYMBOL_SCOPE/SYMBOL_VERSION 指令」を参照してください。

表 7-35 ELF 動的位置フラグ DT_POSFLAG_1

名前
意味
DF_P1_LAZYLOAD
0x1
遅延読み込みされた依存関係を示します。
DF_P1_GROUPPERM
0x2
グループの依存関係を示します。
DF_P1_LAZYLOAD

後続の DT_NEEDED エントリが遅延読み込み対象のオブジェクトであることを示します。このフラグは、リンカーの -z lazyload オプションを使用してオブジェクトに記録されます。「動的依存関係の遅延読み込み」を参照してください。

DF_P1_GROUPPERM

後続の DT_NEEDED エントリがグループとして読み込まれるオブジェクトであることを示します。このフラグは、リンカーの -z groupperm オプションを使用してオブジェクトに記録されます。「グループの分離」を参照してください。

大域オフセットテーブル (プロセッサ固有)

一般に位置独立のコードには絶対仮想アドレスは存在できません。大域オフセットテーブルは、内部で使用するデータ内に絶対アドレスを保持します。このため、位置からの独立性とプログラムのテキストの共有性を低下させることなくアドレスが使用可能になります。プログラムは、位置独立のアドレス指定を使用して GOT を参照し、絶対値を抽出します。この方法により、位置独立の参照を、絶対位置にリダイレクトできます。

最初は、GOT は再配置エントリで要求される情報を保持します。システムが読み込み可能オブジェクトファイルのメモリーセグメントを作成したあと、実行時リンカーが再配置エントリを処理します。これらの再配置のいくつかは、R_xxxx_GLOB_DAT タイプで GOT を参照する場合があります。

実行時リンカーは、関連付けられているシンボル値を判定し、絶対アドレスを計算し、適切なメモリーテーブルエントリに正しい値を設定します。リンカーがオブジェクトファイルを作成するとき、絶対アドレスは認識されていませんが、実行時リンカーはすべてのメモリーセグメントのアドレスを認識しており、したがって、これらのメモリーセグメントに存在するシンボルの絶対アドレスを計算できます。

プログラムがシンボルの絶対アドレスへの直接アクセスを必要とする場合、このシンボルには GOT エントリが存在します。実行可能ファイルと共有オブジェクトには別個の GOT が存在するので、シンボルのアドレスはいくつかのテーブルに現れることがあります。実行時リンカーは、すべての GOT の再配置を処理してから、プロセスイメージ内のいずれかのコードに制御を渡します。この処理により、実行時に絶対アドレスが利用可能になります。

テーブルのエントリ 0 は、_DYNAMIC シンボルで参照される動的構造体のアドレスを保持するために予約されています。このシンボルを利用することにより、実行時リンカーなどのプログラムは、再配置エントリを処理していなくても自身の動的構造体を見つけることができます。この方法は、実行時リンカーにとって特に重要です。なぜなら、実行時リンカーはほかのプログラムに頼ることなく自身を初期化してメモリーイメージを再配置しなければならないからです。

システムは、異なるプログラムの同じ共有オブジェクトに対して、異なるメモリーセグメントアドレスを与えることがあります。さらに、システムはプログラムを実行するごとに異なるライブラリアドレスを与えることさえあります。しかし、プロセスイメージがいったん作成されると、メモリーセグメントのアドレスは変更されません。プロセスが存在するかぎり、そのプロセスのメモリーセグメントは固定仮想されたアドレスに存在します。

GOT の形式と解釈は、プロセッサに固有です。_GLOBAL_OFFSET_TABLE_ シンボルは、テーブルをアクセスするために使用できます。このシンボルは、.got セクションの中央に存在可能であるため、負の添字と負でない添字の両方をアドレスの配列に含めることができます。シンボルタイプは、32 ビットコードの場合、Elf 32_Addr の配列で、64 ビットコードの場合、Elf 64_Addr の配列です。

extern  Elf32_Addr  _GLOBAL_OFFSET_TABLE_[];
extern  Elf64_Addr  _GLOBAL_OFFSET_TABLE_[];

プロシージャーのリンクテーブル (プロセッサ固有)

大域オフセットテーブルは位置独立のアドレスの計算を絶対位置に変換します。同様に、プロシージャーのリンクテーブルは位置独立の関数呼び出しを絶対位置に変換します。リンカーは、異なる動的オブジェクト間の実行転送 (関数呼び出しなど) を解決できません。このため、リンカーはプログラム転送制御をプロシージャーのリンクテーブルのエントリに与えます。このようにして実行時リンカーは、位置からの独立性とプログラムのテキストの共有性を低下させることなくエントリをリダイレクトします。実行可能ファイルと共有オブジェクトファイルには、別個のプロシージャーのリンクテーブルが存在します。

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

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

最初の 4 つのプロシージャーのリンクテーブルエントリは、予約されています。表 7-36 に例示されてはいますが、これらのエントリの元の内容は指定されていません。テーブル内の各エントリは 3 ワード (12 バイト) を占めており、最後のテーブルエントリの後には nop 命令が続きます。

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

プロシージャーのリンクテーブルを説明するため、表 7-36 に 4 つのエントリが示されています。4 つのエントリのうちの 2 つは初期状態で予約されているエントリです。3 番目のエントリは name101 に対する呼び出しです。4 番目のエントリは name102 に対する呼び出しです。この例では、name102 のエントリがテーブルの最後のエントリであることを前提としています。この最後のエントリの後には nop 命令が続きます。左欄は、動的リンクが行われる前のオブジェクトファイルの命令を示しています。右欄は、実行時リンカーがプロシージャーリンクテーブルのエントリを変更するために使用できる命令シーケンスを示しています。

表 7-36 32 ビット SPARC: プロシージャーのリンクテーブルの例

オブジェクトファイル
メモリーセグメント
.PLT0:
    unimp
    unimp
    unimp
.PLT1:
    unimp
    unimp
    unimp
.PLT0:
    save    %sp, -64, %sp
    call    runtime_linker
    nop
.PLT1:
    .word   identification
    unimp
    unimp
.PLT101:
    sethi   (.-.PLT0), %g1
    ba,a    .PLT0
    nop
.PLT102:
    sethi   (.-.PLT0), %g1
    ba,a    .PLT0
    nop

    nop
.PLT101:
    nop
    ba,a    name101
    nop
.PLT102:
    sethi   (.-.PLT0), %g1
    sethi   %hi(name102), %g1
    jmpl    %g1+%lo(name102), %g0
    
    nop

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

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

  2. ほかのすべてのプロシージャーのリンクテーブルエントリは、最初は先頭エントリに渡されます。これで、実行時リンカーは各テーブルエントリの最初の実行時に制御を取得します。たとえば、プログラムが name101 を呼び出すと、制御がラベル .PLT101 に渡されます。

  3. sethi 命令は、現在のプロシージャーのリンクテーブルエントリ (.PLT101) と最初のプロシージャーのリンクテーブルエントリ (.PLT0) の距離を計算します。この値は、%g1 レジスタの最上位 22 ビットを占めます。

  4. 次に、ba,a 命令が .PLT0 にジャンプして、スタックフレームを作成し、実行時リンカーを呼び出します。

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

  6. 実行時リンカーは、%g1 値をシフトしプロシージャーのリンクテーブルエントリのサイズで除算することで、 name101 の再配置エントリのインデックスを計算します。再配置エントリ 101 のタイプは R_SPARC_JMP_SLOT です。再配置オフセットは .PLT101 のアドレスを指定し、また、そのシンボルテーブルインデックスは name101 を参照します。したがって、実行時リンカーはシンボルの実際の値を取得し、スタックを戻し、プロシージャーのリンクテーブルエントリに変更を加え、本来の宛先に制御を渡します。

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


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


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

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

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

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

表 7-37 64 ビット 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. プログラムのメモリーイメージが最初に作成されると、実行時リンカーはプロシージャーのリンクテーブルの初期エントリを変更します。エントリは、実行時リンカー自身のルーチンに制御を渡すように修正されます。実行時リンカーはまた、識別情報 (identification) の拡張ワードを 3 番目のエントリに格納します。実行時リンカーが制御を受け取ると、このワードは呼び出したオブジェクトを見つけるために調べられます。

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

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

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

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

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

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


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


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

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

32 ビット x86 動的オブジェクトの場合、プロシージャーリンクテーブルは共有テキスト内に存在しますが、非公開の大域オフセットテーブル内のアドレスを使用します。実行時リンカーは、宛先の絶対アドレスを判定し、これらの絶対アドレスに従って大域オフセットテーブルのメモリーイメージに変更を加えます。このようにして実行時リンカーは、位置からの独立性とプログラムのテキストの共有性を低下させることなくエントリをリダイレクトします。実行可能ファイルと共有オブジェクトファイルには、別個のプロシージャーのリンクテーブルが存在します。

表 7-38 32 ビット x86: 絶対プロシージャーのリンクテーブルの例

.PLT0:
    pushl   got_plus_4
    jmp     *got_plus_8
    nop;    nop
    nop;    nop
.PLT1:
    jmp     *name1_in_GOT
    pushl   $offset
    jmp     .PLT0@PC
.PLT2:
    jmp     *name2_in_GOT
    pushl   $offset
    jmp     .PLT0@PC

表 7-39 32 ビット x86: 位置独立のプロシージャーリンクテーブルの例

.PLT0:
    pushl   4(%ebx)
    jmp     *8(%ebx)
    nop;    nop
    nop;    nop
.PLT1:
    jmp     *name1@GOT(%ebx)
    pushl   $offset
    jmp     .PLT0@PC
.PLT2:
    jmp     *name2@GOT(%ebx)
    pushl   $offset
    jmp     .PLT0@PC

注 - 前述の例が示すとおり、プロシージャーリンクテーブルの命令は、絶対コードと位置独立のコードで異なるオペランドアドレス指定モードを使用します。それでも、実行時リンカーへのインタフェースは同一です。


次の手順は、実行時リンカーとプログラムがプロシージャーのリンクテーブルおよび大域オフセットテーブルによってシンボル参照をどのように協同で解決するかを示しています。

  1. 実行時リンカーは、プログラムのメモリーイメージを最初に作成するとき、大域オフセットテーブルの 2 番目と 3 番目のエントリに特殊な値を設定します。これらの値については、次の手順で説明します。

  2. プロシージャーのリンクテーブルが位置独立の場合、大域オフセットテーブルのアドレスは、%ebx に存在しなければなりません。プロセスイメージにおける各共有オブジェクトファイルには自身のプロシージャーのリンクテーブルが存在しており、制御は同じオブジェクトファイル内からのみプロシージャーのリンクテーブルエントリに渡されます。したがって、呼び出し側関数は、プロシージャーのリンクテーブルエントリを呼び出す前に、大域オフセットテーブルベースレジスタをセットしなければなりません。

  3. たとえば、プログラムが name1 を呼び出すと、制御が .PLT1 に渡されます。

  4. 最初の命令は、name1 の大域オフセットテーブルエントリのアドレスにジャンプします。大域オフセットテーブルは最初は、後続の pushl 命令のアドレスを保持します (name1 の実アドレスは保持しない)。

  5. プログラムは再配置オフセット (offset) をスタックにプッシュします。再配置オフセットは、再配置テーブルへの 32 ビットの負ではないバイトオフセットです。指定された再配置エントリには R_386_JMP_SLOT が存在しており、オフセットは、前の jmp 命令で使用された大域オフセットテーブルエントリを指定します。再配置エントリにはシンボルテーブルインデックスも存在しており、実行時リンカーはこれを使って参照されたシンボル name1 を取得します。

  6. プログラムは、再配置オフセットをプッシュした後、.PLT0 (プロシージャーのリンクテーブルの先頭エントリ) にジャンプします。pushl 命令は、2 番目の大域オフセットテーブルエントリ (got_plus_4 または 4(%ebx)) の値をスタックにプッシュして、実行時リンカーに 1 ワードの識別情報を与えます。プログラムは次に、3 番目の大域オフセットテーブルエントリ (got_plus_8 または 8(%ebx)) のアドレスにジャンプして、実行時リンカーにジャンプします。

  7. 実行時リンカーはスタックを戻し、指定された再配置エントリを調べ、シンボルの値を取得し、name1 の実際のアドレスを大域オフセットテーブルエントリに格納し、そして宛先にジャンプします。

  8. その後のプロシージャーのリンクテーブルエントリに対する実行は、name1 に直接渡されます (実行時リンカーの再呼び出しは行われない)。.PLT1 における jmp 命令は、pushl 命令にジャンプする代わりに、name1 にジャンプします。

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

x64: プロシージャーのリンクテーブル

x64 動的オブジェクトの場合、プロシージャーリンクテーブルは共有テキスト内に存在しますが、非公開の大域オフセットテーブル内のアドレスを使用します。実行時リンカーは、宛先の絶対アドレスを判定し、これらの絶対アドレスに従って大域オフセットテーブルのメモリーイメージに変更を加えます。このようにして実行時リンカーは、位置からの独立性とプログラムのテキストの共有性を低下させることなくエントリをリダイレクトします。実行可能ファイルと共有オブジェクトファイルには、別個のプロシージャーのリンクテーブルが存在します。

表 7-40 x64: プロシージャーのリンクテーブルの例

.PLT0:
    pushq   GOT+8(%rip)                         # GOT[1]
    jmp     *GOT+16(%rip)                       # GOT[2]
    nop;    nop
    nop;    nop
.PLT1:
    jmp     *name1@GOTPCREL(%rip)               # 16 bytes from .PLT0
    pushq   $index1
    jmp     .PLT0
.PLT2:
    jmp     *name2@GOTPCREL(%rip)               # 16 bytes from .PLT1
    pushl   $index2
    jmp     .PLT0

次の手順は、実行時リンカーとプログラムがプロシージャーのリンクテーブルおよび大域オフセットテーブルによってシンボル参照をどのように協同で解決するかを示しています。

  1. 実行時リンカーは、プログラムのメモリーイメージを最初に作成するとき、大域オフセットテーブルの 2 番目と 3 番目のエントリに特殊な値を設定します。これらの値については、次の手順で説明します。

  2. プロセスイメージにおける各共有オブジェクトファイルには自身のプロシージャーのリンクテーブルが存在しており、制御は同じオブジェクトファイル内からのみプロシージャーのリンクテーブルエントリに渡されます。

  3. たとえば、プログラムが name1 を呼び出すと、制御が .PLT1 に渡されます。

  4. 最初の命令は、name1 の大域オフセットテーブルエントリのアドレスにジャンプします。大域オフセットテーブルは最初は、後続の pushq 命令のアドレスを保持します (name1 の実アドレスは保持しない)。

  5. プログラムは再配置インデックス (index1) をスタックにプッシュします。再配置オフセットは、再配置テーブルへの 32 ビットの負ではないインデックスです。再配置テーブルは DT_JUMPREL 動的セクションエントリによって識別されます。指定された再配置エントリには R_AMD64_JMP_SLOT が存在しており、オフセットは、前の jmp 命令で使用された大域オフセットテーブルエントリを指定します。再配置エントリにはシンボルテーブルインデックスも存在しており、実行時リンカーはこれを使って参照されたシンボル name1 を取得します。

  6. プログラムは、再配置インデックスをプッシュした後、.PLT0 (プロシージャーのリンクテーブルの先頭エントリ) にジャンプします。pushq 命令は、2 番目の大域オフセットテーブルエントリ (GOT+8) の値をスタックにプッシュして、実行時リンカーに 1 ワードの識別情報を与えます。プログラムは次に、3 番目の大域オフセットテーブルエントリ (GOT+16) のアドレスにジャンプして、実行時リンカーにジャンプします。

  7. 実行時リンカーはスタックを戻し、指定された再配置エントリを調べ、シンボルの値を取得し、name1 の実際のアドレスを大域オフセットテーブルエントリに格納し、そして宛先にジャンプします。

  8. その後のプロシージャーのリンクテーブルエントリに対する実行は、name1 に直接渡されます (実行時リンカーの再呼び出しは行われない)。.PLT1 における jmp 命令は、pushq 命令にジャンプする代わりに、name1 にジャンプします。

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