すでに述べたとおり、オブジェクトファイルはプログラムのリンクと実行の両方に関係します。利便性と効率性のため、オブジェクトファイルの形式には、リンクと実行の異なる要求に合わせて、2 つの平行した見方があります。図 7-1 にオブジェクトファイルの編成を示します。
ELF ヘッダーはオブジェクトファイルの先頭に存在し、ファイル編成を記述する「ロードマップ」を保持します。
「セクション」は、ELF ファイル内で処理可能な最小単位 (これ以上分割できない単位) です。「セグメント」は、exec(2) または実行時リンカーでメモリイメージに対応付けできる最小単位 (これ以上分割できない単位) です。
セクションは、リンクの観点から見たオブジェクトファイルの情報 (命令、データ、シンボルテーブル、再配置情報など) の大部分を保持します。セクションに関しては、この章の前半で説明します。セグメントとプログラムの実行の観点から見たファイルの構造に関しては、この章の後半で説明します。
プログラムヘッダーテーブル (存在する場合) は、システムにプロセスイメージの作成方法を通知します。プロセスイメージの作成に使用されるファイル (実行可能プログラムと共有オブジェクト) には、プログラムヘッダーテーブルが存在しなければなりません。再配置可能オブジェクトには、プログラムヘッダーテーブルは存在する必要はありません。
セクションヘッダーテーブルには、ファイルのセクションを記述する情報が入っています。セクションヘッダーテーブルには各セクションのエントリが存在します。各エントリは、セクション名、セクションサイズなどの情報が含まれます。リンク編集で使用されるファイルには、セクションヘッダーテーブルが存在しなければなりません。他のオブジェクトファイルには、セクションヘッダーテーブルは存在してもしなくてもかまいません。
図では ELF ヘッダの直後にプログラムヘッダーテーブルが示され、セクションヘッダーテーブルがセクションの後に続いていますが、実際のファイルは異なる場合があります。また、セクションとセグメントの順序は特に決まっていません。ELF ヘッダーの位置のみがファイル内で固定されています。
ここで記述されているとおり、オブジェクトファイルの形式は、8 ビットバイト、 32 ビットアーキテクチャおよび 64 ビットアーキテクチャを持つさまざまなプロセッサをサポートしていますが、オブジェクトファイルの形式は、より大きな (またはより小さな) アーキテクチャに拡張できることを意図しています。
したがって、オブジェクトファイルはマシンに依存しない形式になっているいくつかの制御データを表現し、その結果、オブジェクトファイルが識別でき、オブジェクトファイルの内容が共通した方法で解釈できます。オブジェクトファイルの残りのデータは、このオブジェクトファイルが作成されたマシンとは関係なく、対象となるプロセッサ用に符号化されています。
表 7-1 32 ビットデータタイプ
名前 |
サイズ |
整列 |
目的 |
---|---|---|---|
Elf32_Addr |
4 |
4 |
符号なしプログラムアドレス |
Elf32_Half |
2 |
2 |
符号なし、中程度の整数 |
Elf32_Off |
4 |
4 |
符号なしファイルオフセット |
Elf32_Sword |
4 |
4 |
符号付き整数 |
Elf32_Word |
4 |
4 |
符号なし整数 |
unsigned char |
1 |
1 |
符号なし、短い整数 |
表 7-2 64 ビットデータタイプ
名前 |
サイズ |
整列 |
目的 |
---|---|---|---|
Elf64_Addr |
8 |
8 |
符号なしプログラムアドレス |
Elf64_Half |
2 |
2 |
符号なし、中程度の整数 |
Elf64_Off |
8 |
8 |
符号なしファイルオフセット |
Elf64_Sword |
4 |
4 |
符号付き整数 |
Elf64_Word |
4 |
4 |
符号なし整数 |
Elf64_Xword |
8 |
8 |
符号なし、長い整数 |
Elf64_Sxword |
8 |
8 |
符号付き、長い整数 |
unsigned char |
1 |
1 |
符号なし、短い整数 |
オブジェクトファイルの形式で定義されるすべてのデータ構造は、該当クラスの自然なサイズと整列ガイドラインに従います。必要であれば、データ構造に明示的にパッドを入れることで、4 バイトオブジェクトに対して 4 バイト整列を保証したり構造サイズを 4 の倍数に設定したりします。また、データはファイルの先頭から適切に整列されます。したがってたとえば、Elf32_Addr 構成要素が存在する構造はファイル内において 4 バイト境界で整列され、Elf64_Addr 構成要素が存在する構造は 8 バイト境界で整列されます。
移植性を考慮して、ELF ではビットフィールドを使用していません。
いくつかのオブジェクトファイル制御構造は大きくなることがありまが、その大きさは ELF ヘッダーに記録されます。オブジェクトファイルの形式が変わった場合、ELF 形式のファイルにアクセスするプログラムは、大きくなったり小さくなったりした制御構造体を扱うことになります。大きくなった場合は、追加された部分を無視することができるかもしれません。小さくなった場合は、無くなった部分の扱いは状況に依存しますし、形式が変更された時に規定されるでしょう。
ELF ヘッダーの構造体 (sys/elf.h で定義されている) は、以下のとおりです。
#define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr; typedef struct { unsigned char e_ident[EI_NIDENT]; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr; |
先頭のバイト列に、オブジェクトファイルであることを示す印と、機種に依存しない、ファイルの内容を復号化または解釈するためのデータが入ります。完全な記述は、「ELF 識別」で行われています。
この構成要素は、オブジェクトファイルの種類を示します。
名前 |
値 |
意味 |
---|---|---|
ET_NONE |
0 |
ファイルタイプが存在しない |
ET_REL |
1 |
再配置可能ファイル |
ET_EXEC |
2 |
実行可能ファイル |
ET_DYN |
3 |
共有オブジェクトファイル |
ET_CORE |
4 |
コアファイル |
ET_LOPROC |
0xff00 |
プロセッサに固有 |
ET_HIPROC |
0xffff |
プロセッサに固有 |
コアファイルの内容は指定されていませんが、ET_CORE タイプはコアファイルを示すために予約されます。ET_LOPROC から ET_HIPROC までの値 (それぞれを含む) は、プロセッサ固有の方法で解釈されます。他の値は予約され、必要に応じて新しいオブジェクトファイルの種類に割り当てられます。
この構成要素の値は、個々のファイルが必要とするアーキテクチャを指定します。
名前 |
値 |
意味 |
---|---|---|
EM_NONE |
0 |
マシンが存在しない |
EM_M32 |
1 |
AT&T WE 32100 |
EM_SPARC |
2 |
SPARC |
EM_386 |
3 |
Intel 80386 |
EM_68K |
4 |
Motorola 68000 |
EM_88K |
5 |
Motorola 88000 |
EM_486 |
6 |
Intel 80486 |
EM_860 |
7 |
Intel 80860 |
EM_MIPS |
8 |
MIPS RS3000 Big-Endian |
EM_MIPS_RS3_LE |
10 |
MIPS RS3000 Little-Endian |
EM_RS6000 |
11 |
RS6000 |
EM_PA_RISC |
15 |
PA-RISC |
EM_nCUBE |
16 |
nCUBE |
EM_VPP500 |
17 |
Fujitsu VPP500 |
EM_SPARC32PLUS |
18 |
Sun SPARC 32+ |
EM_PPC |
20 |
PowerPC |
EM_SPARCV9 |
43 |
SPARC V9 |
他の値は予約され、必要に応じて新しい機種に割り当てられます。プロセッサ固有の ELF 名の識別には、機種名が使用されます。たとえば、以下に述べるフラグでは接頭辞 EF_ が使用されます。EM_XYZ マシンの WIDGET というフラグは、EF_XYZ_WIDGET と呼ばれます。
この構成要素は、オブジェクトファイルのバージョンを示します。
名前 |
値 |
意味 |
---|---|---|
EV_NONE |
0 |
無効なバージョン |
EV_CURRENT |
>=1 |
現バージョン |
値 1 は最初のファイル形式を示し、拡張した場合は番号を大きくします。EV_CURRENT の値は、現バージョン番号を示すために必要に応じて変化します。
この構成要素は、システムが制御を最初に渡す仮想アドレスを保持します。仮想アドレスが与えられると、プロセスが起動されます。ファイルに関連する入り口点が存在しない場合、この構成要素は 0 を保持します。
この構成要素は、プログラムヘッダーテーブルのファイルオフセット (単位 : バイト) を保持します。ファイルにプログラムヘッダーテーブルが存在しない場合、この構成要素は 0 を保持します。
この構成要素は、セクションヘッダーテーブルのファイルオフセット (単位 : バイト) を保持します。ファイルにセクションヘッダーテーブルが存在しない場合、この構成要素は 0 を保持します。
この構成要素は、ファイルに対応付けられているプロセッサ固有のフラグを保持します。フラグ名は、EF_machine「_flag」という形式をとります。この構成要素は現在、SPARC と x86 に対して 0 です。
表 7-6 SPARCV9 用 ELF フラグ
名前 |
値 |
意味 |
---|---|---|
EF_SPARCV9_MM |
0x3 |
メモリーモデルのマスク |
EF_SPARCV9_TSO |
0x0 |
Total Store Ordering |
EF_SPARCV9_PSO |
0x1 |
Partial Store Ordering |
EF_SPARCV9_RMO |
0x2 |
Relaxed Memory Ordering |
EF_SPARC_EXT_MASK |
0xffff00 |
ベンダー拡張マスク |
EF_SPARC_SUN_US1 |
0x000200 |
Sun UltraSPARC 1 拡張 |
EF_SPARC_HAL_R1 |
0x000400 |
HAL R1 拡張 |
EF_SPARC_SUN_US3 |
0x000800 |
Sun UltraSPARC 3 拡張 |
この構成要素は、ELF ヘッダーのサイズ (単位 : バイト) を保持します。
この構成要素は、ファイルのプログラムヘッダーテーブルの 1 つのエントリのサイズ (単位 : バイト) を保持します。すべてのエントリは同じサイズです。
この構成要素は、プログラムヘッダーテーブルのエントリ数を保持します。したがって、e_phentsize に e_phnum を掛けると、テーブルのサイズ (単位 : バイト) が求められます。ファイルにプログラムヘッダーテーブルが存在しない場合、e_phnum は値 0 を保持します。
この構成要素は、1 つのセクションヘッダーのサイズ (単位 : バイト) を保持します。1 つのセクションヘッダーは、セクションヘッダーテーブルの 1 つのエントリです。すべてのエントリは同じサイズです。
この構成要素は、セクションヘッダーテーブルのエントリ数を保持します。したがって、e_shentsize に e_shnum を掛けると、セクションヘッダーテーブルのサイズ (単位: バイト) が求められます。ファイルにセクションヘッダーテーブルが存在しない場合、e_shnum は値 0 を保持します。
この構成要素は、セクション名文字列テーブルに対応するエントリのセクションヘッダーテーブルインデックスを保持します。ファイルにセクション名文字列テーブルが存在しない場合、この構成要素は値 SHN_UNDEF を保持します。詳細は、「セクション」と 「文字列テーブル」を参照してください。
先に述べたとおり、ELF はオブジェクトファイルの枠組みを提供し、複数のプロセッサ、複数のデータ符号化、複数のクラスのマシンをサポートします。このオブジェクトファイルファミリをサポートできるようファイルの初期バイトは、問い合わせが行われるプロセッサに関係なくかつファイルの残りの内容にも関係なくファイルの解釈方法を指定します。
ELF ヘッダー (とオブジェクトファイル) の初期バイトは、e_ident 構成要素に一致します。
表 7-7 e_ident[ ] 識別インデックス
名前 |
値 |
目的 |
---|---|---|
EI_MAG0 |
0 |
ファイルの識別 |
EI_MAG1 |
1 |
ファイルの識別 |
EI_MAG2 |
2 |
ファイルの識別 |
EI_MAG3 |
3 |
ファイルの識別 |
EI_CLASS |
4 |
ファイルのクラス |
EI_DATA |
5 |
データの符号化 |
EI_VERSION |
6 |
ファイルのバージョン |
EI_PAD |
7 |
パッドバイトの開始 |
EI_NIDENT |
16 |
e_ident[] のサイズ |
次のインデックスは、マジックナンバーを保持するバイトをアクセスします。
ファイルの先頭 4 バイトは、ファイルを ELF オブジェクトファイルとして識別する「マジックナンバー」を保持します。
名前 |
値 |
位置 |
---|---|---|
ELFMAG0 |
0x7f |
e_ident[EI_MAG0] |
ELFMAG1 |
'E' |
e_ident[EI_MAG1] |
ELFMAG2 |
'L' |
e_ident[EI_MAG2] |
ELFMAG3 |
'F' |
e_ident[EI_MAG3] |
その次のバイト e_ident[EI_CLASS] は、ファイルのクラス、または容量を示します。
名前 |
値 |
意味 |
---|---|---|
ELFCLASSNONE |
0 |
無効なクラス |
ELFCLASS32 |
1 |
32 ビットオブジェクト |
ELFCLASS64 |
2 |
64 ビットオブジェクト |
ファイル形式は、最大マシンのサイズを最小マシンに押しつけることなしにさまざまなサイズのマシン間で互換性が維持されるように設計されています。クラス ELFCLASS32 は、4 ギガバイトまでのファイルと仮想アドレス空間が存在するマシンをサポートし、また以前に定義した基本タイプを使用します。
クラス ELFCLASS64 は、SPARCV9 などの 64 ビットアーキテクチャに対して使用されます。
バイト e_ident[EI_DATA] は、オブジェクトファイルのプロセッサ固有のデータの符号化を指定します。現在、以下の符号化が定義されています。
名前 |
値 |
意味 |
---|---|---|
ELFDATANONE |
0 |
無効な符号化 |
ELFDATA2LSB |
1 |
図 7-2 を参照 |
ELFDATA2MSB |
2 |
図 7-3 を参照 |
これらの符号化の詳細を以下に示します。他の値は予約され、必要に応じて新しい符号化に割り当てられます。
バイト e_ident[EI_VERSION] は、ELF ヘッダーバージョン番号を指定します。現在この値は、e_version の表 7-5 で説明されているように、EV_CURRENT でなければなりません。
この値は、e_ident の使用されていないバイトの先頭を示します。これらのバイトは保留され、0 に設定されます。オブジェクトファイルを読み取るプログラムは、これらのバイトを無視するべきです。使用されていないバイト列が使用されるようになった場合、EI_PAD の値は変更されます。
ファイルのデータ符号化方式は、ファイルの基本オブジェクトを解釈する方法を指定します。先に述べたとおり、クラス ELFCLASS32 のファイルは、1、2、および 4 バイトを占めるオブジェクトを使用します。定義されている符号化方式の下では、オブジェクトは以下のように表されます。バイト番号は、左上隅に示されています。
ELFDATA2LSB を符号化すると、最下位バイトが最低位アドレスを占める 2 の補数値が指定されます。
ELFDATA2MSB を符号化すると、最上位バイトが最低位アドレスを占める 2 の補数値が指定されます。
オブジェクトファイルのセクションヘッダーテーブルを使用すると、すべてのファイルのセクションを見つけ出すことができます。セクションヘッダーテーブルは、以下に示されているとおり、Elf32_Shdr 構造体または Elf64_Shdr 構造体の配列です。セクションヘッダーテーブルインデックスは、この配列への添字です。ELF ヘッダーの e_shoff 構成要素は、ファイルの先頭からセクションヘッダーテーブルまでのバイトオフセットを与えます。e_shnum は、セクションヘッダーテーブルに存在するエントリ数を与えます。e_shentsize は、各エントリのサイズ (単位 : バイト) を与えます。
いくつかのセクションヘッダーテーブルインデックスは予約されます。オブジェクトファイルには、これらの特殊インデックスのセクションは存在しません。
表 7-11 セクションの特殊インデックス
名前 |
値 |
---|---|
SHN_UNDEF |
0 |
SHN_LORESERVE |
0xff00 |
SHN_LOPROC |
0xff00 |
SHN_BEFORE |
0xff00 |
SHN_AFTER |
0xff01 |
SHN_HIPROC |
0xff1f |
SHN_ABS |
0xfff1 |
SHN_COMMON |
0xfff2 |
SHN_HIRESERVE |
0xffff |
この値は、未定義の、または失われた、または関連のない、または無意味なセクション参照を示します。たとえば、セクション番号 SHN_UNDEF に関して「定義された」シンボルは、未定義シンボルです。
インデックス 0 は未定義値として予約されますが、セクションヘッダーテーブルにはインデックス 0 のエントリが存在します。つまり、ELF ヘッダーの e_shnum 構成要素が、ファイルのセクションヘッダーテーブルに 6 つのエントリが存在することを示している場合、これら 6 つのエントリにはインデックス 0 から 5 までが与えられます。先頭のエントリの内容は、この項の末尾に記述します。
この値は、予約されているインデックスの範囲の下限を指定します。
この範囲の値は、プロセッサ固有の使用方法に予約されます。
これらの値は、SHF_ORDERED セクションフラグと共に先頭および末尾セクションに順序付けを行います (表 7-14 を参照)。
この値は、対応する参照の絶対値を示します。たとえば、セクション番号 SHN_ABS からの相対で定義されたシンボルは絶対値をとり、再配置の影響を受けません。
このセクションに関して定義されたシンボルは、共通シンボルです。たとえば、FORTRAN COMMON や割り当てられていない C 外部変数です。これらのシンボルは、ときどき一時的シンボルと呼ばれることもあります。
この値は、予約されているインデックスの範囲の上限を指定します。システムは、SHN_LORESERVE から SHN_HIRESERVE までのインデックスを予約します。値は、セクションヘッダーテーブルを参照しません。つまり、セクションヘッダーテーブルには予約されているインデックスのエントリは存在しません。
セクションには、ELF ヘッダー、プログラムヘッダーテーブル、セクションヘッダーテーブルを除く、オブジェクトファイルのすべての情報が存在します。また、オブジェクトファイルのセクションは以下の条件を満たします。
オブジェクトファイルの各セクションには、そのセクションを記述するセクションヘッダーが必ず 1 つ存在する。対応するセクションが存在しないセクションヘッダーが存在することもある
各セクションは、ファイル内で連続するバイトシーケンス (空の場合もある) を占める
ファイル内のセクション同士は重ならない。ファイル内のどのバイトも複数のセクションに属することはない
オブジェクトファイルには、使用されていない領域が存在することがある。さまざまなヘッダーとセクションは、オブジェクトファイルのすべてのバイトをカバーしないことがある。使用されていないデータの内容は不定
セクションヘッダーの構造体 (sys/elf.h で定義されている) は、次のとおりです。
typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize; } Elf32_Shdr; typedef struct { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; } Elf64_Shdr; |
この構成要素は、セクション名を指定します。値はセクションヘッダーの文字列テーブルセクション (「文字列テーブル」を参照) へのインデックスで、空文字 で終わっている文字列を指し示します。セクション名とその説明は、表 7-16 を参照してください。
この構成要素は、セクションの内容と意味を分類します。セクションの種類とその説明は、表 7-12 を参照してください。
セクションは、さまざまな属性を記述する 1 ビットフラグをサポートします。フラグの定義は、表 7-14 を参照してください。
セクションがプロセスのメモリーイメージに現れる場合、この構成要素はセクションの先頭バイトが存在しなければならないアドレスを与えます。セクションがプロセスのメモリーイメージに現れない場合、この構成要素には 0 が存在します。
この構成要素は、ファイルの先頭からセクションの先頭バイトまでのバイトオフセットを与えます。以下に説明されている SHT_NOBITS 型のセクションは、ファイルのスペースを占めません。sh_offset 構成要素は、ファイル内の概念上の位置を示します。
この構成要素は、セクションのサイズ (単位 : バイト) を与えます。セクションの型が SHT_NOBITS でない限り、セクションはファイルの sh_size バイトを占めます。タイプが SHT_NOBITS のセクションは、0 以外のサイズをとることがありますが、ファイルのスペースは占めません。
この構成要素は、セクションヘッダーテーブルインデックスリンクを保持します。このリンクの解釈は、セクションの型に依存します。値は、表 7-15 を参照してください。
この構成要素は、追加的な情報を保持します。追加的な情報の解釈は、セクションの型に依存します。値は、表 7-15 を参照してください。
いくつかのセクションには、アドレス整列制約が存在します。たとえば、あるセクションが 2 語で構成されるデータを保持している場合、システムはそのセクション全体に対して 2 語単位の整列を保証しなければなりません。つまり、sh_addr の値は、sh_addralign の値を法として 0 でなければなりません。現在、0、および 2 の非負整数累乗のみが許されています。値 0 と 1 は、セクションに整列制約が存在しないことを意味します。
いくつかのセクションは、サイズが一定のエントリのテーブル (シンボルテーブルなど) を保持します。このようなセクションに対してこの構成要素は、各エントリのサイズ (単位 : バイト) を与えます。サイズが一定のエントリのテーブルをセクションが保持しない場合、この構成要素には 0 が格納されます。
セクションヘッダーの sh_type 構成要素は、このセクションの意味を指定します。
表 7-12 sh_type が保持するセクションの型
名前 |
値 |
---|---|
SHT_NULL |
0 |
SHT_PROGBITS |
1 |
SHT_SYMTAB |
2 |
SHT_STRTAB |
3 |
SHT_RELA |
4 |
SHT_HASH |
5 |
SHT_DYNAMIC |
6 |
SHT_NOTE |
7 |
SHT_NOBITS |
8 |
SHT_REL |
9 |
SHT_SHLIB |
10 |
SHT_DYNSYM |
11 |
SHT_SUNW_move |
0x6ffffffa |
SHT_SUNW_COMDAT |
0x6ffffffb |
SHT_SUNW_syminfo |
0x6ffffffc |
SHT_SUNW_verdef |
0x6ffffffd |
SHT_SUNW_verneed |
0x6ffffffe |
SHT_SUNW_versym |
0x6fffffff |
SHT_LOPROC |
0x70000000 |
SHT_HIPROC |
0x7fffffff |
SHT_LOUSER |
0x80000000 |
SHT_HIUSER |
0xffffffff |
この値は、該当セクションヘッダーが使用されないものであることを示します。このセクションには、関連付けられているセクションは存在しません。セクションヘッダーの他の構成要素の値は不定です。
このセクションは、プログラムで定義された情報を保持します。プログラムの形式と意味は、プログラムが独自に決定します。
これらのセクションは、シンボルテーブルを保持します。一般に、SHT_SYMTAB セクションはリンク編集に関するシンボルを与えます。このセクションには完全なシンボルテーブルとして、動的リンクに不要な多くのシンボルが存在することがあります。また、オブジェクトファイルには SHT_DYNSYM セクション (最小の一群の動的リンクシンボルを保持して領域を節約している) が存在することがあります。詳細は、「シンボルテーブル」を参照してください。
これらのセクションは、文字列テーブルを保持します。オブジェクトファイルには、複数の文字列テーブルセクションが存在できます。詳細は、「文字列テーブル」を参照してください。
このセクションは、明示的加数が存在する再配置エントリ (32 ビットクラスのオブジェクトファイルの Elf32_Rela タイプなど) を保持します。オブジェクトファイルには、複数の再配置セクションが存在できます。詳細は、「再配置」を参照してください。
このセクションは、シンボルハッシュテーブルを保持します。動的にリンクされたすべてのオブジェクトファイルには、シンボルハッシュテーブルが存在しなければなりません。現在、オブジェクトファイルにはハッシュテーブルは 1 つしか存在できませんが、この制約は将来、緩和されるかもしれません。詳細は、「ハッシュテーブル」を参照してください。
このセクションは、動的リンクに関する情報を保持します。現在、オブジェクトファイルには動的リンクのセクションは 1 つしか存在できませんが、この制約は将来、緩和されるかもしれません。詳細は、「動的セクション」を参照してください。
このセクションは、何らかの方法でファイルを示す情報を保持します。詳細は、「注釈セクション」を参照してください。
この型のセクションはファイルの領域を占めませんが、他の点では SHT_PROGBITS に類似しています。このセクションにはデータは存在しませんが、sh_offset 構成要素には概念上のファイルオフセットが存在します。
このセクションは、明示的加数が存在しない再配置エントリ (32 ビットクラスのオブジェクトファイルの Elf32_Rel 型など) を保持します。オブジェクトファイルには、複数の再配置セクションが存在できます。詳細は、「再配置」を参照してください。
このセクション型は予約されていますが、解釈の方法は定義されていません。この型のセクションが存在するプログラムは、ABI に準拠しません。
このセクションには、部分的に初期化されたシンボルを扱うデータが存在します。
このセクションには、部分的に初期化されたシンボルを扱うデータが存在します。
このセクションには、追加シンボル情報を保持するテーブルが存在します。
このセクションには、このファイルで定義されているきめの細かいバージョンの定義が存在します。
このセクションには、イメージの実行に必要なきめの細かい依存性の記述が存在します。
このセクションには、シンボルとバージョン定義 (ファイルが与える) の関係を記述するテーブルが存在します。
この範囲の値は、プロセッサ固有な使用方法用に予約されます。
この値は、アプリケーションプログラムに対して予約されるインデックスの範囲の下限を示します。
この値は、アプリケーションプログラムに対して予約されるインデックスの範囲の上限を示します。SHT_LOUSER から SHT_HIUSER までのセクション型は、現在の、または将来のシステム定義セクション型と競合することなくアプリケーションで使用できます。
他のセクション型の値は、保留されています。先に述べたとおり、インデックス 0 (SHN_UNDEF) のセクションヘッダーは存在します (このインデックスが未定義セクション参照を示してもです)。このエントリは、以下のものを保持します。
表 7-13 セクションヘッダーのテーブルエントリ : インデックス 0
名前 |
値 |
注意 |
---|---|---|
sh_name |
0 |
名前が存在しない |
sh_type |
SHT_NULL |
使用されない |
sh_flags |
0 |
フラグが存在しない |
sh_addr |
0 |
アドレスが存在しない |
sh_offset |
0 |
ファイルオフセットが存在しない |
sh_size |
0 |
サイズが存在しない |
sh_link |
SHN_UNDEF |
リンク情報が存在しない |
sh_info |
0 |
補助情報が存在しない |
sh_addralign |
0 |
整列が存在しない |
sh_entsize |
0 |
エントリが存在しない |
セクションヘッダーの sh_flags構成要素は、セクションの属性を記述する 1 ビットフラグを保持します。
表 7-14 セクションの属性のフラグ
名前 |
値 |
---|---|
SHF_WRITE |
0x1 |
SHF_ALLOC |
0x2 |
SHF_EXECINSTR |
0x4 |
SHF_ORDERED |
0x40000000 |
SHF_EXCLUDE |
0x80000000 |
SHF_MASKPROC |
0xf0000000 |
sh_flags にフラグビットが設定されると、属性がセクションに対して「オン」になります。設定されない場合は、属性が「オフ」になるか、または適用されません。定義されていない属性は保留され、0 に設定されています。
このセクションには、プロセス実行時に書き込み可能でなければならないデータが存在します。
このセクションは、プロセス実行時にメモリーを占めます。いくつかの制御セクションは、オブジェクトファイルのメモリーイメージに存在しません。この属性は、これらのセクションに対してオフです。
このセクションには、実行可能なマシン命令が存在します。
このセクションは、同じ型の他のセクションと順序付けられます。順序付けられるセクションは、sh_link エントリでポイントされるセクション内で結合されます。順序付けられるセクションの sh_link エントリは、自身を指し示すことがあります。
順序付けられるセクションの sh_info エントリが同一入力ファイル内の有効セクションの場合、順序付けられるセクションは、sh_info エントリでポイントされるセクションの出力ファイル内の相対順序付けに基づいて整列されます。特殊な sh_info 値である SHN_BEFORE または SHN_AFTER (表 7-11を参照) は、整列対象セクションが順序付け対象となる他のすべてのセクションの前または後に存在することを意味します。順序付けの対象となるセクションの複数にこれらの特殊値の 1 つが存在する場合、入力ファイルが指定された順序は保存されます。
sh_info 順序付け情報が存在しない場合、出力ファイルの 1 つのセクション内で結合される 1 つの入力ファイルからのセクションは連続的になり、入力ファイル内の相対順序付けと同じ相対順序付けになります。複数の入力ファイルからの場合は、リンクコマンドで指定された順序になります。
このセクションは、実行可能オブジェクトまたは共有オブジェクトのリンク編集への入力から除かれます。このフラグは、SHF_ALLOC フラグが設定されている場合、またはセクションに対する参照が存在する場合、無視されます。
このマスクに存在するすべてのビットは、プロセッサ固有な使用方法に予約されます。
セクションヘッダーの 2 つの構成要素 sh_link と sh_info は、セクション型に従って特殊な情報を保持します。
表 7-15 sh_link と sh_info の解釈
sh_type |
sh_link |
sh_info |
---|---|---|
SHT_DYNAMIC |
関連付けられている文字列テーブルのセクションヘッダーインデックス |
0 |
SHT_HASH |
関連付けられているシンボルテーブルのセクションヘッダーインデックス |
0 |
SHT_REL SHT_RELA |
関連付けられているシンボルテーブルのセクションヘッダーインデックス |
再配置が適用されるセクションのセクションヘッダーインデックス。表 7-16 も参照 |
SHT_SYMTAB SHT_DYNSYM |
関連付けられている文字列テーブルのセクションヘッダーインデックス |
最後の局所シンボルのシンボルテーブルインデックスより 1 大きい (STB_LOCAL に対応する) |
SHT_SUNW_move |
関連付けられているシンボルテーブルのセクションヘッダーインデックス |
0 |
SHT_SUNW_COMDAT |
0 |
0 |
SHT_SUNW_syminfo |
関連付けられているシンボルテーブルのセクションヘッダーインデックス |
関連付けられている動的セクションのセクションヘッダーインデックス |
SHT_SUNW_verdef |
関連付けられている文字列テーブルのセクションヘッダーインデックス |
セクション内のバージョン定義数 |
SHT_SUNW_verneed |
関連付けられている文字列テーブルのセクションヘッダーインデックス |
セクション内のバージョン依存数 |
SHT_SUNW_versym |
関連付けられているシンボルテーブルのセクションヘッダーインデックス |
0 |
other |
SHN_UNDEF |
0 |
さまざまなセクションがプログラム情報と制御情報を保持します。以下の一覧表に示されているセクションはシステムで使用されますが、これらのセクションには一覧表で示されている型と属性が存在します。
表 7-16 特殊セクション
名前 |
型 |
属性 |
---|---|---|
.bss |
SHT_NOBITS |
SHF_ALLOC + SHF_WRITE |
.comment |
SHT_PROGBITS |
なし |
.data |
SHT_PROGBITS |
SHF_ALLOC + SHF_WRITE |
.data1 |
SHT_PROGBITS |
SHF_ALLOC + SHF_WRITE |
.dynamic |
SHT_DYNAMIC |
SHF_ALLOC + SHF_WRITE |
.dynstr |
SHT_STRTAB |
SHF_ALLOC |
.dynsym |
SHT_DYNSYM |
SHF_ALLOC |
.fini |
SHT_PROGBITS |
SHF_ALLOC + SHF_EXECINSTR |
.got |
SHT_PROGBITS | |
.hash |
SHT_HASH |
SHF_ALLOC |
.init |
SHT_PROGBITS |
SHF_ALLOC + SHF_EXECINSTR |
.interp |
SHT_PROGBITS | |
.note |
SHT_NOTE |
なし |
.plt |
SHT_PROGBITS | |
.rela |
SHT_RELA |
なし |
.relname |
SHT_REL |
「再配置」を参照 |
.relaname |
SHT_RELA |
「再配置」を参照 |
.rodata |
SHT_PROGBITS |
SHF_ALLOC |
.rodata1 |
SHT_PROGBITS |
SHF_ALLOC |
.shstrtab |
SHT_STRTAB |
なし |
.strtab |
SHT_STRTAB |
後続の .strtab 記述を参照 |
.symtab |
SHT_SYMTAB |
「シンボルテーブル」を参照 |
.text |
SHT_PROGBITS |
SHF_ALLOC + SHF_EXECINSTR |
.SUNW_bss |
SHT_NOBITS |
SHF_ALLOC + SHF_WRITE |
.SUNW_heap |
SHT_PROGBITS |
SHF_ALLOC + SHF_WRITE |
.SUNW_move |
SHT_SUNW_move |
SHF_ALLOC |
.SUNW_reloc |
SHT_rel SHT_rela |
SHF_ALLOC |
.SUNW_syminfo |
SHT_SUNW_syminfo |
SHF_ALLOC |
.SUNW_version |
SHT_SUNW_verdef SHT_SUNW_verneed SHT_SUNW_versym |
SHF_ALLOC |
このセクションは、プログラムのメモリーイメージで使用される初期化されていないデータを保持します。システムは、プログラムが実行を開始すると 0 でデータを初期化することになっています。このセクションは、セクション型 SHT_NOBITS で示されているとおり、ファイルスペースを占めません。
このセクションは、コメント情報を保持します。
これらのセクションは、プログラムのメモリーイメージに使用される初期化されているデータを保持します。
このセクションは、動的リンク情報を保持します。
このセクションは、動的リンクに必要な文字列 (最も一般的には、シンボルテーブルエントリに関連付けられている名前を表す文字列) を保持します。
このセクションは、動的リンクシンボルテーブルを保持します。詳細は、「シンボルテーブル」を参照してください。
このセクションは、プロセス終了時に使用される実行可能命令を保持します。つまり、プログラムが正常終了すると、システムはこのセクションの命令を実行できるようにします。
このセクションは、大域オフセットテーブルを保持します。詳細は、「大域オフセットテーブル (プロセッサ固有)」を参照してください。
このセクションは、シンボルハッシュテーブルを保持します。詳細は、「ハッシュテーブル」を参照してください。
このセクションは、プロセス初期化時に使用される実行可能命令を保持します。つまり、プログラムが実行を開始すると、システムはプログラム入り口点を呼び出す前にこのセクションの命令を実行できるようにします。
このセクションは、プログラムインタプリタのパス名を保持します。詳細は、「プログラムインタプリタ」を参照してください。
このセクションは、「注釈セクション」に記述されている形式で情報を保持します。
このセクションは、手続きリンクテーブルを保持します。詳細は、「手続きリンクテーブル (プロセッサに固有)」を参照してください。
このセクションは、レジスタ再配置情報を保持します。
これらのセクションは、再配置情報 (「再配置」に記述されている) を保持します。再配置が存在する読み込み可能セグメントがファイルに存在する場合、これらのセクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。慣例により、name は再配置が適用されるセクションの名前になります。したがって、.text の再配置セクションには、通常 .rel.text または .rela.text という名前が存在します。
これらのセクションは、読み取り私用データを保持します。はこのデータは、一般にはプロセスイメージの書き込み不能セグメントに使用されます。詳細は、「プログラムヘッダー」を参照してください。
このセクションは、セクション名を保持します。
このセクションは、文字列 (最も一般的には、シンボルテーブルエントリに関連付けられている名前を表す文字列) を保持します。シンボル文字列テーブルが存在する読み込み可能セグメントがファイルに存在する場合、セクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。
このセクションは、「シンボルテーブル」に記述されているとおり、シンボルテーブルを保持します。シンボルテーブルが存在する読み込み可能セグメントがファイルに存在する場合、セクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。
このセクションは、プログラムの「テキスト」すなわち実行可能命令を保持します。
このセクションは、プログラムのメモリーイメージで使用される、実行不能共有オブジェクトの部分的に初期化されたデータを保持します。データは実行時に初期化されます。このセクションは、セクション型 SHT_NOBITS で示されているとおり、ファイル領域を占めません。
このセクションは、 dldump(3X) によって作成される動的実行可能プログラムのデータ領域 (ヒープ) を保持します。
このセクションは、部分的に初期化されたデータに関する追加情報を保持します。「移動セクション」を参照してください。
このセクションは、「再配置」で記述されているとおり、再配置情報を保持します。このセクションは再配置セクションが連結されたものであり、個々の再配置レコードに対するより良い参照の局所性を与えます。再配置レコード自身のオフセットのみが意味があり、したがって、セクション sh_info の値は 0 です。
このセクションは、シンボルテーブルの追加情報を保持します。詳細は、「Syminfo テーブル」 を参照してください。
この名前を持つセクションは、バージョン情報を保持します。詳細は、「バージョン情報」を参照してください。
ドット (.) 接頭辞付きのセクション名はシステムにおいて予約されています。これらのセクションの既存の意味が満足できるものであれば、アプリケーションはこれらのセクションを使用できます。アプリケーションは、ドット (.) 接頭辞なしの名前を使用して、システムで予約されたセクションとの競合を回避することができます。オブジェクトファイル形式では、上記リストに記載されていないセクションが定義できます。オブジェクトファイルには、同じ名前を持つ複数のセクションが存在できます。
プロセッサアーキテクチャに対して予約されるセクション名は、アーキテクチャ名の省略形をセクション名の前に入れることで作成されます。セクション名の前に、e_machine に対して使用されるアーキテクチャ名を入れる必要があります。たとえば、.Foo.psect は、FOO アーキテクチャで定義される psect セクションです。
既存の拡張セクションは、従来から使用されている名前をそのまま使用しています。
既存の拡張セクション
.conflict |
.liblist |
.lit8 |
.sdata |
.debug |
.line |
.reginfo |
.stab |
.gptab |
.lit4 |
.sbss |
.tdesc |
文字列テーブルセクションは、空文字 で終了する一連の文字 (一般に文字列と呼ばれている) を保持します。オブジェクトファイルは、これらの文字列を使用してシンボルとセクション名を表します。文字列は、文字列テーブルセクションへのインデックスとして参照されます。
先頭バイト (インデックス 0) は、空文字を保持します。同様に、文字列テーブルの最後のバイトは、空文字を保持します。したがって、すべての文字列はが確実に空文字で終了します。インデックスが 0 の文字列は、名前を指定しないかまたは空文字の名前を指定します (状況に依存する)。
空の文字列テーブルセクションが許されており、このセクションのセクションヘッダーの sh_size 構成要素に 0 が入ります。0 以外のインデックスは、空の文字列テーブルに対して無効です。
セクションヘッダーの sh_name 構成要素は、ELF ヘッダーの e_shstrndx 構成要素で示されているとおり、セクションヘッダー文字列テーブルセクションへのインデックスを保持します。次に示されている図は、25 バイトの文字列テーブルと、さまざまなインデックスに関連付けられている文字列を示しています。
下の表は、上に示した文字列テーブルの文字列を示しています。
表 7-17 文字列テーブルインデックス
インデックス |
文字列 |
---|---|
0 |
「なし」 |
1 |
name. |
7 |
Variable |
11 |
able |
16 |
able |
24 |
「空文字列」 |
例に示されているとおり、文字列テーブルインデックスはセクションのすべてのバイトを参照できます。文字列は 2 回以上現れることができ、部分文字列に対する参照は存在でき、単一文字列は複数回参照できます。参照されない文字列も許されます。
オブジェクトファイルのシンボルテーブルは、プログラムのシンボル定義/参照の探索と再配置に必要な情報を保持します。シンボルテーブルインデックスは、この配列への添字です。インデックス 0 はシンボルテーブルの先頭エントリを指定し、また未定義シンボルインデックスとして機能します。先頭エントリの内容は、このセクションの後の方で記述します。
表 7-18 シンボルテーブルの先頭エントリ
名前 |
値 |
---|---|
STN_UNDEF |
0 |
シンボルテーブルエントリの形式 (sys/elf.h で定義されている) は、次のとおりです。
typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_Sym; typedef struct { Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym; |
この構成要素は、オブジェクトファイルのシンボル文字列テーブルへのインデックス (シンボル名の文字表現を保持する) を保持します。値が 0 以外の場合、その値はシンボル名を与える文字列テーブルインデックスを表します。値が 0 の場合、シンボルテーブルエントリに名前は存在しません。
外部 C シンボルは、C とオブジェクトファイルのシンボルテーブルにおいて同じ名前を持ちます。
この構成要素は、関連付けられているシンボルの値を与えます。この値は、絶対値やアドレスなど (状況に依存する) を表します。「シンボル値」を参照してください。
多くのシンボルは、関連付けられている大きさを持っています。たとえば、データオブジェクトのサイズは、データオブジェクトに存在するバイト数です。この構成要素は、シンボルが大きさを持っていない場合または大きさが不明な場合、0 を保持します。
この構成要素は、シンボルの種類と結び付けられる属性を指定します。値と意味のリストを以下に示します。次のコードは、値 (sys/elf.h で定義されている) の処理方法を示します。
#define ELF32_ST_BIND(i) ((i) >> 4) #define ELF32_ST_TYPE(i) ((i) & 0xf) #define ELF32_ST_INFO(b, t) (((b)<<4)+((t)&0xf)) #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) #define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) |
この構成要素は現在 0 を保持しており、意味は定義されていません。
すべてのシンボルテーブルエントリは、何らかのセクションに関して定義されます。この構成要素は、該当するセクションヘッダーテーブルインデックスを保持します。いくつかのセクションインデックスは、特別な意味を示します。表 7-12 を参照してください。
名前 |
値 |
---|---|
STB_LOCAL |
0 |
STB_GLOBAL |
1 |
STB_WEAK |
2 |
STB_LOPROC |
13 |
STB_HIPROC |
15 |
局所シンボルは、局所シンボルの定義が存在するオブジェクトファイルの外部では見えません。同じ名前の局所シンボルは、互いに干渉することなく複数のファイルに存在できます。
大域シンボルは、結合されるすべてのオブジェクトファイルで見ることができます。あるファイルの大域シンボルの定義は、その大域シンボルへの別ファイルの未定義参照を解決します。
ウィークシンボルは大域シンボルに似ていますが、ウィークシンボルの定義の優先順位は大域シンボルの定義より低いです。
この範囲の値は、プロセッサ固有の使用方法に対して予約されます。
大域シンボルとウィークシンボルは、主に 2 つの点で異なります。
リンカーは、いくつかの再配置可能オブジェクトファイルを結合するとき、同じ名前の STB_GLOBAL シンボルの複数の定義を許しない。一方、定義された大域シンボルが存在している場合、同じ名前のウィークシンボルが現れてもエラーは発生しない。リンカーは大域定義を使用し、弱い定義を無視する
同様に、共通シンボルが存在している場合 (つまり、SHN_COMMON を保持している st_index フィールドが存在するシンボルが存在している場合)、同じ名前のウィークシンボルが現れてもエラーは発生しない。リンカーは共通定義を使用し、弱い定義を無視する
リンカーは、アーカイブライブラリ (「アーカイブ処理」を参照) を検索するとき、大域シンボル (未定義または一時的) の定義が存在するアーカイブ構成要素を抜き出す。構成要素の定義は、大域シンボルまたはウィークシンボル
リンカーはデフォルトでは、未定義のウィークシンボルを解決するためのアーカイブ構成要素を抜き出さない。解決されていないウィークシンボルは、値 0 を持ち。-z weakextract を使用すると、このデフォルトの動作が無効になり、弱い参照がアーカイブ構成要素を抜き出すことができる。
各シンボルテーブルにおいて、STB_LOCAL 結び付きが存在するすべてのシンボルは、ウィークシンボルと大域シンボルの前に存在します。「セクション」に記述されているとおり、シンボルテーブルセクションの sh_info セクションヘッダー構成要素は、最初の局所的ではないシンボルに対するシンボルテーブルインデックスを保持します。
シンボルの種類は、関連付けられている実体に関する一般的分類を行います。
表 7-20 シンボルの種類 (ELF32_ST_TYPE、ELF64_ST_TYPE)
名前 |
値 |
---|---|
STT_NOTYPE |
0 |
STT_OBJECT |
1 |
STT_FUNC |
2 |
STT_SECTION |
3 |
STT_FILE |
4 |
STT_LOPROC |
13 |
STT_SPARC_REGISTER |
13 |
STT_HIPROC |
15 |
シンボルの種類は指定されません。
シンボルは、データオブジェクト (変数や配列など) と関連付けられています。
シンボルは、関数または他の実行可能コードに関連付けられています。
シンボルは、セクションに関連付けられています。この種類のシンボルテーブルエントリは主に再配置を行うために存在しており、通常、STB_LOCAL に結び付けられています。
慣例により、シンボルの名前はオブジェクトファイルに対応するソースファイルの名前を与えます。ファイルシンボルは STB_LOCAL に結び付けられており、セクションインデックスは SHN_ABS であり、ファイルシンボル (存在する場合) はファイルの他の STB_LOCAL シンボルの前に存在します。SHT_SYMTAB のシンボルインデックス 1 は、ファイル自身を表す STT_FILE シンボルです。慣例により、この後にはファイルの STT_SECTION シンボルと、局所シンボルに短縮されている大域シンボルが続きます (詳細は、「シンボル範囲の縮小」と、第 5 章「バージョンアップ」を参照してください。)
この範囲の値は、プロセッサ固有の使用方法に対して予約されます。
共有オブジェクトファイルの関数シンボル (STT_FUNC タイプが存在する) は、特別な意味を持っています。別のオブジェクトファイルが共有オブジェクトの関数を参照すると、リンカーは参照されるシンボルの手続きリンクテーブルエントリを自動的に作成します。STT_FUNC 以外のタイプの共有オブジェクトシンボルは、手続きリンクテーブルから自動的には参照されません。
シンボル値がセクション内の特定位置を参照すると、セクションインデックス構成要素 st_shndx は、セクションヘッダーテーブルへのインデックスを保持します。再配置時にセクションが移動すると、シンボル値も変化し、シンボルへの参照はプログラム内の同じ位置を指し示し続けます。いくつかの特別なセクションインデックス値は、他の意味付けがされています。
シンボルは、絶対値 (再配置が行われても変化しない) を持ちます。
シンボルは、割り当てられていない共通ブロックを示します。シンボル値は、セクションの sh_addralign 構成要素に類似した整列制約を与えます。つまり、リンカーは st_value の倍数のアドレスにシンボル記憶領域を割り当てます。シンボルの大きさは、必要なバイト数を示します。
このセクションテーブルインデックスは、シンボルが未定義であることを意味します。リンカーがこのオブジェクトファイルを、示されたシンボルを定義する他のオブジェクトファイルに結合すると、このシンボルに対するこのファイルの参照は実際の定義に結び付けられます。
前述したとおり、インデックス 0 (STN_UNDEF) のシンボルテーブルエントリは予約されています。このシンボルテーブルエントリは以下の値を保持します。
表 7-21 シンボルテーブルエントリ: インデックス 0
名前 |
値 |
注意 |
---|---|---|
st_name |
0 |
名前はない |
st_value |
0 |
値は 0 |
st_size |
0 |
サイズはない |
st_info |
0 |
種類はない。局所結び付き |
st_other |
0 |
|
st_shndx |
SHN_UNDEF |
セクションは存在しない |
異なる複数のオブジェクトファイル型のシンボルテーブルエントリは、st_value 構成要素に対してわずかに異なる解釈を持ちます。
再配置可能ファイルでは、st_value はセクションインデックスが SHN_COMMON であるシンボルに対する整列制約を保持する
再配置可能ファイルでは、st_value は定義されたシンボルに対するセクションオフセットを保持する。つまり、st_value は、st_shndx が識別するセクションの先頭からのオフセット
実行可能オブジェクトファイルと共有オブジェクトファイルでは、st_value は仮想アドレスを保持する。これらのファイルのシンボルを実行時リンカーに対してより有用にするために、セクションオフセット (ファイル解釈) の代わりに、セクション番号が無関係な仮想アドレス (ファイル解釈) が使用される
シンボルテーブル値は、異なる種類のオブジェクトファイルでも似た意味を持ちますが、適切なプログラムはデータに効率的にアクセスできます。
SPARC アーキテクチャは、レジスタシンボル (大域レジスタを初期化するシンボル) をサポートします。レジスタシンボルに対するシンボルテーブルエントリには、以下の値が入ります。
表 7-22 シンボルテーブルエントリ: レジスタシンボル
フィールド |
意味 |
---|---|
st_name |
シンボル名文字列テーブルへのインデックス。または 0 (スクラッチレジスタ) |
st_value |
レジスタ番号。整数レジスタの割り当てについては、ABI マニュアルを参照 |
st_size |
未使用 (0) |
st_info |
結び付きは標準的には STB_GLOBAL。種類は STT_SPARC_REGISTER でなければならない |
st_other |
未使用 (0) |
st_shndx |
SHN_ABS (このオブジェクトがこのレジスタシンボルを初期化する場合)。SHN_UNDEF (それ以外の場合) |
表 7-23 SPARC レジスタ番号
名前 |
値 |
意味 |
---|---|---|
STO_SPARC_REGISTER_G2 |
0x2 |
%g2 |
STO_SPARC_REGISTER_G3 |
0x3 |
%g3 |
特定の大域レジスタのエントリが存在しないことは、その特定の大域レジスタがオブジェクトで使用されないことを意味します。
このセクションには、Elf32_Syminfo 型または Elf64_Syminfo 型の複数のエントリが存在します。関連付けられているシンボルテーブルの各エントリ (sh_link) の 「.SUNW_syminfo」セクションには、1 つのエントリが存在します。このセクションがオブジェクトに存在している場合、関連付けられているシンボルテーブルからシンボルインデックスを取り出し、このシンボルインデックスを使ってこのセクションに存在する対応する Elf32_Syminfo または Elf64_Syminfo エントリを見つけることで、追加シンボル情報を見つけます。関連付けられているシンボルテーブルと、Syminfo テーブルには、必ず同じ数のエントリが存在します。インデックス 0 は、Syminfo テーブルの現バージョン (SYMINFO_CURRENT) を格納するために使用されます。シンボルテーブルエントリ 0 は必ず UNDEF シンボルテーブルエントリに対して予約されるので、矛盾は発生しません。
Elf32_Symfino エントリの形式は、以下のとおりです。
typedef struct { Elf32_Half si_boundto; /* direct bindings - symbol bound to */ Elf32_Half si_flags; /* per symbol flags */ } Elf32_Syminfo; typedef struct { Elf64_Half si_boundto; /* direct bindings - symbol bound to */ Elf64_Half si_flags; /* per symbol flags */ } Elf64_Syminfo; |
これはビットフィールドであり、以下のフラグを設定できます。
表 7-24 Syminfo フラグ
名前 |
値 |
意味 |
---|---|---|
SYMINFO_FLG_DIRECT |
0x01 |
このシンボルは、オブジェクトに直接結び付けられる |
SYMINFO_FLG_COPY |
0x02 |
このシンボルは、コピー - 再配置を行った結果 |
sh_info フィールドで示される .dynamic セクションのエントリへのインデックス。このエントリは、DT_* (DT_NEEDED) エントリ (Syminfo エントリに関連付けられている動的オブジェクトを示す) を示します。次の 2 つのエントリは、si_boundto に対して予約されます。
表 7-25 si_boundto 予約値
名前 |
値 |
意味 |
---|---|---|
SYMINFO_BT_SELF |
0xffff |
自己に結び付けられるシンボル |
SYMINFO_BT_PARENT |
0xfffe |
親に結合されるシンボル。親は、この動的オブジェクトの読み込みを発生させる最初のオブジェクト |
再配置は、記号参照を記号定義に関連付ける処理です。たとえば、プログラムが関数を呼び出すとき、関連付けられている呼び出し命令は、実行時に適切な宛先アドレスに制御を渡さなければなりません。つまり、再配置可能ファイルには、セクション内容の変更方法を示す情報が存在しなければなりません。その結果、実行可能オブジェクトファイルと共有オブジェクトファイルは、プロセスのプログラムイメージに関する正しい情報を保持できます。再配置エントリはこれらのデータを保持します。
再配置エントリは、以下の構造体 (sys/elf.h で定義されている) を持つことができます。
typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; } Elf32_Rel; typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; Elf32_Sword r_addend; } Elf32_Rela; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; } Elf64_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; Elf64_Sxword r_addend; } Elf32_Rela; |
この構成要素は、再配置処理を適用する位置を与えます。再配置可能ファイルの場合、値はセクションの先頭から再配置の影響を受ける領域までのオフセットです。実行可能ファイルまたは共有オブジェクトの場合、値は再配置の影響を受ける領域の仮想アドレスです。
この構成要素は、再配置が行われなければならないシンボルテーブルインデックスと、適用される再配置の種類を与えます。たとえば、呼び出し命令の再配置エントリは、呼び出される関数のシンボルテーブルインデックスを保持します。インデックスが STN_UNDEF (未定義シンボルインデックス) の場合、再配置はシンボル値として 0 を使用します。再配置の種類はプロセッサに固有です。再配置の種類の動作は以下に記述します。以下のテキストが再配置エントリの再配置の種類またはシンボルテーブルインデックスを参照すると、それぞれ ELF32_R_TYPE または ELF32_R_SYM をエントリの r_info 構成要素に適用した結果が得られます。
#define ELF32_R_SYM(i) ((i)>>8) #define ELF32_R_TYPE(i) ((unsigned char)(i)) #define ELF32_R_INFO(s, t) (((s)<<8)+(unsigned char)(t)) #define ELF64_R_SYM(info) ((info)>>32) #define ELF64_R_TYPE(info) ((Elf64_Word)(info)) #define ELF64_R_INFO(sym, type)(((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(type)) |
Elf64_Rel および Elf64_Rela 構造の場合、r_info フィールドはさらに 8 ビットの識別子と 24 ビットの付随的なデータに分割されます。
#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) #define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) #define ELF64_R_TYPE_INFO(data, type)(((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) |
この構成要素は、再配置可能フィールドに格納される値の計算に使用される定数加数を指定します。
前述したとおり、Elf32_Rela エントリにのみ明示的加数が存在します。Elf32_Rel エントリには、変更される位置に暗黙の加数が存在します。SPARC は Elf32_Rela エントリを使用し、x86 は Elf32_Rel エントリを使用し、SPARCV9 は Elf64_Rela エントリを使用します。
再配置セクションは、他の 2 つのセクション (シンボルテーブルと変更されるセクション) を参照します。セクションヘッダーの sh_info と sh_link 構成要素 (既出の「セクション」に記述されている) は、これらの関係を指定します。異なる複数のオブジェクトファイルに対する再配置エントリには、r_offset 構成要素に関してわずかに異なる解釈が存在します。
再配置可能ファイルでは r_offset は、セクションオフセットを保持する。つまり、再配置セクション自身はファイルの別セクションの変更方法を記述する。再配置オフセットは、2 番目のセクション内の領域を指定する
実行可能オブジェクトファイルと共有オブジェクトファイルでは、r_offset は仮想アドレスを保持する。これらのファイルの再配置エントリを実行時リンカーに対してより有用にするために、セクションオフセット (ファイル解釈) の代わりに、仮想アドレス (メモリー解釈) が使用される
r_offset の解釈は異なる複数のオブジェクトファイルでは変化し、その結果、関連プログラムによる効率的アクセスが可能になっていますが、再配置タイプの意味は変化しません。
SPARC の場合、再配置エントリは以下の命令/データフィールドの変更方法を記述します (ビット番号はボックスの下隅に表示される)。
x86 の場合、再配置エントリは以下の命令/データフィールドの変更方法を記述します (ビット番号はボックスの下隅に表示される)。
word32 は、任意バイト整列が存在する 4 バイトを占める 32 ビットフィールドを指定します。これらの値は、x86 アーキテクチャにおける他のワード値と同じバイト順序を使用します。
SPARCV9 には、64 ビットワードフィールドが存在します。
以下の計算では、が再配置可能ファイルを実行可能プログラムまたは共有オブジェクトファイルに変換することが仮定されています。概念上、リンカーは 1 つまたは複数の再配置可能ファイルを併合して出力します。リンカーは、まず入力ファイルの結合/配置方法を決め、次にシンボル値を更新し、最後に再配置を行います。実行可能オブジェクトファイルと共有オブジェクトファイルに適用される再配置は類似しており、同じ結果を実現します。後述の説明では、以下の表記が使用されています。
再配置可能フィールドの値を計算するために使用される加数を意味します。
実行時に共有オブジェクトがメモリーに読み込まれる基底アドレスを意味します。一般に共有オブジェクトファイルは 0 基底仮想アドレスで作成されますが、実行アドレスは異なります。基底アドレスについては、「プログラムヘッダー」を参照してください。
実行時に再配置エントリのシンボルのアドレスが存在する「大域オフセットテーブル」へのオフセットを意味します。詳細は、「大域オフセットテーブル (プロセッサ固有)」を参照してください。
「大域オフセットテーブル」のアドレスを意味します。詳細は、「大域オフセットテーブル (プロセッサ固有)」を参照してください。
シンボルに対する「手続きリンクテーブル」エントリの位置 (セクションオフセットまたはアドレス) を意味します。手続きリンクテーブルエントリは、関数呼び出しを適切な宛先に変更します。リンカーは初期手続きリンクテーブルを作成し、実行時リンカーは実行時にエントリを変更します。詳細は、「手続きリンクテーブル (プロセッサに固有)」を参照してください。
再配置される領域の位置 (セクションオフセットまたはアドレス) (r_offset を使って計算される) を意味します。
インデックスが再配置エントリに存在するシンボルの値を意味します。
SPARC 再配置エントリは、バイト (byte8)、ハーフワード (half16)、またはワード (その他) に適用されます。x86 再配置エントリはワードに適用されます。どの場合も r_offset 値は、影響が与えられる領域の先頭バイトのオフセットまたは仮想アドレスを指定します。再配置タイプは、変更されるビットと、これらのビットの値の計算方法を指定します。
SPARC は明示的加数が存在する Elf32_Rela 再配置エントリのみを使用し、SPARCV9 は Elf64_Rela を使用します。したがって、r_addend 構成要素は再配置加数として機能します。x86 は Elf32_Rel 再配置エントリのみを使用し、再配置されるフィールドは加数を保持します。すべての場合において、加数と計算された結果は同じバイト順序を使用します。
以下の表に示されているフィールド名は、再配置型がオーバーフローを検査するかどうかを通知します。計算される再配置値は意図したフィールドより大きい場合があり、再配置の型によっては値の適合を検証 (V) したり結果を切り捨てたり (T) することがあります。たとえば、V-simm13 は、計算された値が simm13 フィールドの外部に 0 以外の有意ビットを持つことがないことを意味します。
名前 |
値 |
フィールド |
計算 |
---|---|---|---|
R_SPARC_NONE |
0 |
なし |
なし |
R_SPARC_8 |
1 |
V-byte8 |
S + A |
R_SPARC_16 |
2 |
V-half16 |
S + A |
R_SPARC_32 |
3 |
V-word32 |
S + A |
R_SPARC_DISP8 |
4 |
V-byte8 |
S + A - P |
R_SPARC_DISP16 |
5 |
V-half16 |
S + A - P |
R_SPARC_DISP32 |
6 |
V-disp32 |
S + A - P |
R_SPARC_WDISP30 |
7 |
V-disp30 |
(S + A - P) >> 2 |
R_SPARC_WDISP22 |
8 |
V-disp22 |
(S + A - P) >> 2 |
R_SPARC_HI22 |
9 |
T-imm22 |
(S + A) >> 10 |
R_SPARC_22 |
10 |
V-imm22 |
S + A |
R_SPARC_13 |
11 |
V-simm13 |
S + A |
R_SPARC_LO10 |
12 |
T-simm13 |
(S + A) & 0x3ff |
R_SPARC_GOT10 |
13 |
T-simm13 |
G & 0x3ff |
R_SPARC_GOT13 |
14 |
V-simm13 |
G |
R_SPARC_GOT22 |
15 |
T-simm22 |
G >> 10 |
R_SPARC_PC10 |
16 |
T-simm13 |
(S + A - P) & 0x3ff |
R_SPARC_PC22 |
17 |
V-disp22 |
(S + A - P) >> 10 |
R_SPARC_WPLT30 |
18 |
V-disp30 |
(L + A - P) >> 2 |
R_SPARC_COPY |
19 |
なし |
なし |
R_SPARC_GLOB_DAT |
20 |
V-word32 |
S + A |
R_SPARC_JMP_SLOT |
21 |
なし |
R_SPARC_JMP_SLOT を参照 |
R_SPARC_RELATIVE |
22 |
V-word32 |
B + A |
R_SPARC_UA32 |
23 |
V-word32 |
S + A |
R_SPARC_PLT32 |
24 |
V-word32 |
L + A |
R_SPARC_HIPLT22 |
25 |
T-imm22 |
(L + A) >> 10 |
R_SPARC_LOPLT10 |
26 |
T-simm13 |
(L + A) & 0x3ff |
R_SPARC_PCPLT32 |
27 |
V-word32 |
L + A - P |
R_SPARC_PCPLT22 |
28 |
V-disp22 |
(L + A - P) >> 10 |
R_SPARC_PCPLT10 |
29 |
V-simm13 |
(L + A - P) & 0x3ff |
R_SPARC_10 |
30 |
V-simm10 |
S + A |
R_SPARC_11 |
31 |
V-simm11 |
S + A |
R_SPARC_WDISP16 |
40 |
V-d2/disp14 |
(S + A - P) >> 2 |
R_SPARC_WDISP19 |
41 |
V-disp19 |
(S + A - P) >> 2 |
R_SPARC_7 |
43 |
V-imm7 |
S + A |
R_SPARC_5 |
44 |
V-imm5 |
S + A |
R_SPARC_6 |
45 |
V-imm6 |
S + A |
いくつかの再配置型には、単純な計算を超えた意味があります。
この再配置型は R_SPARC_LO10 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_13 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_22 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_WDISP30 に類似しています。ただし、次の点が異なります。つまり、この再配置型はシンボルの手続きリンクテーブルエントリのアドレスを参照し、かつ手続きリンクテーブルを作成するようにリンカーに指示します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。詳細は、「再配置のコピー」を参照してください。
この再配置型は R_SPARC_32 に似ています。ただし、次の点が異なります。つまり、この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、手続きリンクテーブルエントリの位置を与えます。実行時リンカーは、手続きリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスを相対アドレスに加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して 0 を指定しなければなりません。
この再配置型は R_SPARC_32 に似ていますが、整列されていないワードを参照する点が異なります。つまり、再配置されるワードは、任意整列が存在する 4 つの別個のバイトとして処理されなければなりません (アーキテクチャの要求に従って整列されるワードとしては処理されません)。
次の表に示されているフィールド名は、再配置型がオーバーフローを検査するかどうかを通知します。計算される再配置値は意図したフィールドより大きい場合があり、再配置型によっては値の適合を検証 (V) したり結果を切り捨てたり (T) することがあります。たとえば、V-simm13 は、計算された値が simm13 フィールドの外部に 0 以外の有意ビットを持つことがないことを意味します。
名前 |
値 |
フィールド |
計算 |
---|---|---|---|
R_SPARC_NONE |
0 |
なし |
なし |
R_SPARC_8 |
1 |
V-byte8 |
S + A |
R_SPARC_16 |
2 |
V-half16 |
S + A |
R_SPARC_32 |
3 |
V-word32 |
S + A |
R_SPARC_DISP8 |
4 |
V-byte8 |
S + A - P |
R_SPARC_DISP16 |
5 |
V-half16 |
S + A - P |
R_SPARC_DISP32 |
6 |
V-disp32 |
S + A - P |
R_SPARC_WDISP30 |
7 |
V-disp30 |
(S + A - P) >> 2 |
R_SPARC_WDISP22 |
8 |
V-disp22 |
(S + A - P) >> 2 |
R_SPARC_HI22 |
9 |
V-imm22 |
(S + A) >> 10 |
R_SPARC_22 |
10 |
V-imm22 |
S + A |
R_SPARC_13 |
11 |
V-simm13 |
S + A |
R_SPARC_LO10 |
12 |
T-simm13 |
(S + A) & 0x3ff |
R_SPARC_GOT10 |
13 |
T-simm13 |
G & 0x3ff |
R_SPARC_GOT13 |
14 |
V-simm13 |
G |
R_SPARC_GOT22 |
15 |
T-simm22 |
G >> 10 |
R_SPARC_PC10 |
16 |
T-simm13 |
(S + A - P) & 0x3ff |
R_SPARC_PC22 |
17 |
V-disp22 |
(S + A - P) >> 10 |
R_SPARC_WPLT30 |
18 |
V-disp30 |
(L + A - P) >> 2 |
R_SPARC_COPY |
19 |
なし |
なし |
R_SPARC_GLOB_DAT |
20 |
V-xword64 |
S + A |
R_SPARC_JMP_SLOT |
21 |
なし |
R_SPARC_JMP_SLOT を参照 |
R_SPARC_RELATIVE |
22 |
V-xword64 |
B + A |
R_SPARC_UA32 |
23 |
V-word32 |
S + A |
R_SPARC_PLT32 |
24 |
V-word32 |
L + A |
R_SPARC_HIPLT22 |
25 |
T-imm22 |
(L + A) >> 10 |
R_SPARC_LOPLT10 |
26 |
T-simm13 |
(L + A) & 0x3ff |
R_SPARC_PCPLT32 |
27 |
V-disp32 |
L + A - P |
R_SPARC_PCPLT22 |
28 |
V-disp22 |
(L + A - P) >> 10 |
R_SPARC_PCPLT10 |
29 |
V-simm13 |
(L + A - P) & 0x3ff |
R_SPARC_10 |
30 |
V-simm10 |
S + A |
R_SPARC_11 |
31 |
V-simm11 |
S + A |
R_SPARC_64 |
32 |
V-xword64 |
S + A |
R_SPARC_OLO10 |
33 |
V-simm13 |
( (S + A) & 0x3ff) + O |
R_SPARC_HH22 |
34 |
V-imm22 |
(S + A) >> 42 |
R_SPARC_HM10 |
35 |
T-simm13 |
( (S + A) >> 32) & 0x3ff |
R_SPARC_LM22 |
36 |
T-imm22 |
(S + A) >> 10 |
R_SPARC_PC_HH22 |
37 |
V-imm22 |
(S + A - P) >> 42 |
R_SPARC_PC_HM10 |
38 |
T-simm13 |
( (S + A - P) >> 32) & 0x3ff |
R_SPARC_PC_LM22 |
39 |
T-imm22 |
(S + A - P) >> 10 |
R_SPARC_WDISP16 |
40 |
V-d2/disp14 |
(S + A - P) >> 2 |
R_SPARC_WDISP19 |
41 |
V-disp19 |
(S + A - P) >> 2 |
R_SPARC_7 |
43 |
V-imm7 |
(S + A) & 0x7f |
R_SPARC_5 |
44 |
V-imm5 |
(S + A) & 0x1f |
R_SPARC_6 |
45 |
V-imm6 |
(S + A) & 0x3f |
R_SPARC_DISP64 |
46 |
V-xword64 |
S + A - P |
R_SPARC_PLT64 |
47 |
V-xword64 |
L + A |
R_SPARC_HIX22 |
48 |
V-imm22 |
( (S + A) ^ 0xffffffffffffffff) >> 10 |
R_SPARC_LOX10 |
49 |
T-simm13 |
( (S + A) & 0x3ff) | 0x1c00 |
R_SPARC_H44 |
50 |
V-imm22 |
(S + A) >> 22 |
R_SPARC_M44 |
51 |
T-imm10 |
( (S + A) >> 12) & 0x3ff |
R_SPARC_L44 |
52 |
T-imm13 |
(S + A) & 0xfff |
R_SPARC_REGISTER |
53 |
V-xword64 |
S + A |
R_SPARC_UA64 |
54 |
V-xword64 |
S + A |
R_SPARC_UA16 |
55 |
V-half16 |
S + A |
いくつかの再配置型には、単純な計算を超えた意味が存在します。
この再配置型は R_SPARC_LO10 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_13 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_22 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_SPARC_WDISP30 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの手続きリンクテーブルエントリのアドレスを参照し、かつ手続きリンクテーブルを作成するようにリンカーに指示します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。詳細は、「再配置のコピー」を参照してください。
この再配置型は R_SPARC_64 に似ています。ただし、次の点が異なります。つまり、この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。
リンカーは、動的リンクを行うためにこの再配置型を作成します。この再配置型のオフセット構成要素は、手続きリンクテーブルエントリの位置を与えます。実行時リンカーは、手続きリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスを相対アドレスに加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して 0 を指定しなければなりません。
この再配置型は R_SPARC_32 に似ていますが、整列されていないワードを参照する点が異なります。つまり、再配置されるワードは、任意整列が存在する 4 つの別個のバイトとして処理されなければなりません (アーキテクチャの要求に従って整列されるワードとしては処理されません)。
この再配置型は R_SPARC_LO10 に似ていますが、符号付き 13 ビット即値フィールドを十分に使用するために余分なオフセットが追加される点が異なります。
アセンブラは、"imm22-instruction ... %hh (absolute) ..." という形式の命令を認識すると、この再配置型を使用します。
アセンブラは、"simm13-instruction ... %hm (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。
アセンブラは、"imm22-instruction ... %lm (absolute) ..." という形式の命令を認識すると、この再配置型を使用します。この再配置型は R_SPARC_HI22 に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。
アセンブラは、"imm22-instruction ... %hh (pc-relative) ..." という形式の命令を認識すると、この再配置型を使用します。
アセンブラは、"simm13-instruction ... %hm (pc-relative) ..." という形式の命令を認識すると、この再配置型を生成します。
アセンブラは、"imm22-instruction ... %lm (pc-relative) ..." という形式の命令を認識すると、この再配置型を使用します。この再配置型は R_SPARC_PC22 に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。
アセンブラは 7 ビットソフトウェアトラップ番号に対してこの再配置型を使用します。
この再配置型は、64 ビットアドレス空間の最上位 4GB に限定される実行可能ファイルに対して R_SPARC_LOX10 と共に使用されます。R_SPARC_HI22 に似ていますが、リンク値の 1 の補数を与えます。
R_SPARC_HIX22 と共に使用されます。R_SPARC_LO10 に似ていますが、必ずリンク値のビット 10 からビット 12 までを設定します。
アセンブラは、"imm44-instruction ... %h44 (absolute) .." という形式の命令を認識すると、この再配置型を使用します。
アセンブラは、"imm44-instruction ... %m44 (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。
この再配置型は再配置型 R_SPARC_H44 および R_SPARC_M44 と共に使用され、44 ビット絶対アドレス指定モデルを生成します。アセンブラは、"imm44-instruction ... %l44 (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。
この再配置型は、レジスタシンボルを初期化するために使用されます。この再配置型のオフセット構成要素には、初期化されるレジスタ番号が存在します。SHN_ABS 型のこのレジスタには、対応するレジスタシンボルが存在しなければなりません。
名前 |
値 |
フィールド |
計算 |
---|---|---|---|
R_386_NONE |
0 |
none |
なし |
R_386_32 |
1 |
word32 |
S + A |
R_386_PC32 |
2 |
word32 |
S + A - P |
R_386_GOT32 |
3 |
word32 |
G + A |
R_386_PLT32 |
4 |
word32 |
L + A - P |
R_386_COPY |
5 |
なし |
なし |
R_386_GLOB_DAT |
6 |
word32 |
S |
R_386_JMP_SLOT |
7 |
word32 |
S |
R_386_RELATIVE |
8 |
word32 |
B + A |
R_386_GOTOFF |
9 |
word32 |
S + A - GOT |
R_386_GOTPC |
10 |
word32 |
GOT + A - P |
R_386_32PLT |
11 |
word32 |
L + A |
いくつかの再配置型には、単純な計算を超えた意味が存在します。
この再配置型は、大域オフセットテーブルの基底からシンボルの大域オフセットテーブルエントリまでの距離を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型はシンボルの手続きリンクテーブルエントリのアドレスを計算し、かつ手続きリンクテーブルを作成するようにリンカーに指示します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。詳細は、「再配置のコピー」を参照してください。
この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、手続きリンクテーブルエントリの位置を与えます。実行時リンカーは、手続きリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。
リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスに相対アドレスを加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して 0 を指定しなければなりません。
この再配置型は、シンボルの値と大域オフセットテーブルのアドレスの差を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
この再配置型は R_386_PC32 に似ていますが、計算を行う際に大域オフセットテーブルのアドレスを使用する点が異なります。この再配置で参照されるシンボルは、通常 _GLOBAL_OFFSET_TABLE_ です。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。
この種類のセクションは、セクション名 (sh_name) で一意に示されます。リンカーが、同じセクション名の SHT_SUNW_COMDAT 型の複数のセクションと出会うと、最初のセクションが保持され、他のすべてのセクションは捨てられます。また、捨てられた SHT_SUNW_COMDAT セクションに適用されたすべての再配置は無視され、かつ捨てられたセクションで定義されたすべてのシンボルも保持されません。
また、リンカーはセクション命名規約をサポートします。このセクション命名規約は、コンパイラが -Xf オプションで呼び出されるとき、セクションの再順序付け (「セグメントの宣言」を参照) で使用されています。つまり、セクションが、.<funcname>%<sectname> という名前のセクションに入れられると、保持された最後の SHT_SUNW_COMDAT セクションが、.<sectname> で示されるセクションに合体します。この方法を使用すると、SHT_SUNW_COMDAT セクションを最終的に .text または .data または他のセクションに入れることができます。
リンカーで作成されるオブジェクトには、2 つの型のバージョン情報が存在できます。
「バージョン定義」は大域シンボルとの関連付けを与え、SHT_SUNW_verdef および SHT_SUNW_versym 型のセクションを使用して実現される
「バージョン依存性」は他のオブジェクト依存性からのバージョン定義要求を示し、SHT_SUNW_verneed 型のセクションを使用して実現される
これらのセクションを形成する構造体は、sys/link.h で定義されます。バージョン情報が存在するセクションには、.SUNW_version という名前が付けられます。
このセクションは、SHT_SUNW_verdef 型で定義されます。このセクションが存在する場合、SHT_SUNW_versym セクションも存在しなければなりません。これら 2 つの構造体を使用することで、シンボルとバージョン定義の関連付けがファイル内で維持されます (詳細は、「バージョン定義の作成」を参照してください)。このセクションの要素の構造体は、以下のとおりです。
typedef struct { Elf32_Half vd_version; Elf32_Half vd_flags; Elf32_Half vd_ndx; Elf32_Half vd_cnt; Elf32_Word vd_hash; Elf32_Word vd_aux; Elf32_Word vd_next; } Elf32_Verdef; typedef struct { Elf32_Word vda_name; Elf32_Word vda_next; } Elf32_Verdaux; typedef struct { Elf64_Half vd_version; Elf64_Half vd_flags; Elf64_Half vd_ndx; Elf64_Half vd_cnt; Elf64_Word vd_hash; Elf64_Word vd_aux; Elf64_Word vd_next; } Elf64_Verdef; typedef struct { Elf64_Word vda_name; Elf64_Word vda_next; } Elf64_Verdaux; |
この構成要素は、構造体自身のバージョンを示します。
名前 |
値 |
意味 |
---|---|---|
VER_DEF_NONE |
0 |
無効バージョン |
VER_DEF_CURRENT |
>=1 |
現バージョン |
値 1 は最初のセクション形式を示し、拡張した場合は番号を大きくします。VER_DEF_CURRENT の値は、現バージョン番号を示すために必要に応じて変化します。
この構成要素は、バージョン定義に固有の情報を保持します。
名前 |
値 |
意味 |
---|---|---|
VER_FLG_BASE |
0x1 |
ファイル自身のバージョン定義 |
VER_FLG_WEAK |
0x2 |
ウィークバージョン識別子 |
基底バージョン定義は、バージョン定義またはシンボルの自動短縮簡約がファイルに適用されている場合、必ず存在します。基底バージョンは、ファイルの予約されたシンボルに対してデフォルトのバージョンを与えます (「出力イメージの生成」を参照してください)。ウィークバージョン定義には、関連付けられているシンボルは存在しません (詳細は、「ウィークバージョン定義の作成」を参照してください)。
この構成要素は、バージョンインデックスを保持します。各バージョン定義には、SHT_SUNW_versym エントリを適切なバージョン定義に関連付ける一意のインデックスが存在します。
この構成要素は、Elf32_Verdaux 配列の要素数を示します。
この構成要素は、バージョン定義名の値を保持します (この値は、「ハッシュテーブル」に記述されているハッシング機能で生成されます)。
この構成要素は、この Elf32_Verdef エントリの先頭からバージョン定義名の Elf32_Verdaux 配列までのバイトオフセットを保持します。配列の先頭要素は存在しなければならず、この構造体が定義するバージョン定義文字列を指し示します。追加要素は存在することができ、また番号は vd_cnt 値で示されます。これらの要素は、このバージョン定義の依存関係を表します。これらの依存関係の各々は、独自のバージョン定義構造体を持っています。
この構成要素は、この Elf32_Verdef 構造体の先頭から次の Elf32_Verdef エントリまでのバイトオフセットを保持します。
この構成要素は、空文字で終わっている文字列への文字列テーブルオフセットを保持し、バージョン定義名を与えます。
この構成要素は、この Elf32_Verdaux エントリの先頭から次の Elf32_Verdaux エントリまでのバイトオフセットを保持します。
このセクションは SHT_SUNW_versym 型で定義されており、以下の構造を持つ要素配列からなります。
typedef Elf32_Half Elf32_Versym; typedef Elf64_Half Elf64_Versym; |
配列の要素数は、関連付けられているシンボルテーブルに存在するシンボルテーブルエントリ数 (セクション sh_link 値で決定される) に等しくなければなりません。配列の各要素には 1 つのインデックスが存在し、このインデックスは次の値をとることができます。
表 7-31 バージョン依存インデックス
名前 |
値 |
意味 |
---|---|---|
VER_NDX_LOCAL |
0 |
シンボルに局所適用範囲が存在する。 |
VER_NDX_GLOBAL |
1 |
シンボルに大域適用範囲 (基底バージョン定義に割り当てられる) が存在する |
|
>1 |
シンボルに大域適用範囲 (ユーザ定義バージョン定義に割り当てられる) が存在する |
VER_NDX_GLOBAL より大きいインデックス値は、SHT_SUNW_verdef セクションのエントリの vd_ndx 値に一致しなければなりません。VER_NDX_GLOBAL より大きいインデックス値が存在しない場合、SHT_SUNW_verdef セクションが存在する必要はありません。
このセクションは、SHT_SUNW_verneed 型で定義されます。このセクションは、ファイルの動的依存性から要求されるバージョン定義を示すことで、ファイルの動的依存性要求を補足します。依存性にバージョン定義が存在する場合のみ、記録がこのセクションにおいて行われます。このセクションの要素の構造体は、次のとおりです。
typedef struct { Elf32_Half vn_version; Elf32_Half vn_cnt; Elf32_Word vn_file; Elf32_Word vn_aux; Elf32_Word vn_next; } Elf32_Verneed; typedef struct { Elf32_Word vna_hash; Elf32_Half vna_flags; Elf32_Half vna_other; Elf32_Word vna_name; Elf32_Word vna_next; } Elf32_Vernaux; typedef struct { Elf64_Half vn_version; Elf64_Half vn_cnt; Elf64_Word vn_file; Elf64_Word vn_aux; Elf64_Word vn_next; } Elf64_Verneed; typedef struct { Elf64_Word vna_hash; Elf64_Half vna_flags; Elf64_Half vna_other; Elf64_Word vna_name; Elf64_Word vna_next; } Elf64_Vernaux; |
この構成要素は、構造体自身のバージョンを示します。
名前 |
値 |
意味 |
---|---|---|
VER_NEED_NONE |
0 |
無効バージョン |
VER_NEED_CURRENT |
>=1 |
現バージョン |
値 1 は最初のセクション形式を示し、拡張した場合は番号を大きくします。VER_NEED_CURRENT の値は、現バージョン番号を示すために必要に応じて変化します。
この構成要素は、Elf32_Vernaux 配列の要素数を示します。
この構成要素は、空文字で終わっている文字列への文字列テーブルオフセットを保持し、バージョン依存性が存在するファイル名を与えます。この名前は、ファイルに存在する .dynamic 依存性 (「動的セクション」を参照) のどれかに一致します。
この構成要素は、この Elf32_Verneed エントリの先頭から、関連付けられているファイル依存性から要求されるバージョン定義の Elf32_Vernaux 配列までのバイトオフセットを保持します。少なくとも 1 つのバージョン依存性が存在しなければなりません。追加バージョン依存性は存在することができ、また番号は vn_cnt 値で示されます。
この構成要素は、この Elf32_Verneed エントリの先頭から次の Elf32_Verneed エントリまでのバイトオフセットを保持します。
この構成要素は、バージョン依存性の名前のハッシュ値を保持します (この値は、「ハッシュテーブル」に記述されているハッシュ関数で生成されます)。
この構成要素は、バージョン依存性に固有の情報を保持します。
名前 |
値 |
意味 |
---|---|---|
VER_FLG_WEAK |
0x2 |
ウィークバージョン識別子 |
ウィークバージョン依存性は、ウィークバージョン定義への最初の結び付きを示します。詳細は、「バージョン定義の作成」を参照してください。
この構成要素は現在、使用されていません。
この構成要素は、空文字で終わっている文字列への文字列テーブルオフセットを保持し、バージョン依存性の名前を与えます。
この構成要素は、この Elf32_Vernaux エントリの先頭から次の Elf32_Vernaux エントリまでのバイトオフセットを保持します。
ソフトウェアを開発して販売する場合、オブジェクトファイルに特別な情報を付加して、他のプログラムから準拠性や互換性などを確認できるようにしたいことがあります。SHT_NOTE 型のセクションと PT_NOTE 型のプログラムヘッダー要素は、この目的に対して使用できます。
セクションとプログラムヘッダー要素での注釈情報は任意の数のエントリを保持し、これらの各エントリは対象プロセッサの形式になっている 4 バイトワードの配列です。注釈情報の構造についての説明を容易にするためにラベルを図 7-5 に示します。ただし、ラベルは規約の一部ではありません。
name の先頭 namesz バイトには、エントリの所有者または作者を示す、空文字 で終わっている文字列が存在します。名前の競合を回避するための正式な機構は存在しません。慣例では、ベンダーは識別子として自身の名前 ("XYZ Computer Company" など) を使用します。name が存在しない場合、namesz は 0 になります。name の領域は、パッドを使用して、4 バイトに整列します。必要であれば namesz は、パッドの長さを含みません。
desc の先頭 descsz バイトは、注釈記述を保持します。注釈の記述が存在しない場合、descsz は 0 になります。desc の領域は、必要であればパッドを使用して、4 バイトに整列します。descsz はパットの長さを含みません。
このワードは注釈の記述の解釈方法を示します。各エントリの作者は、自分で種類を管理しますので、1 つの type 値に関して複数の解釈が存在することがあります。したがって、注釈の記述を認識するには、name と type の両方を認識しなければなりません。type は現在、負でない値でなければなりません。
たとえば、以下の注釈のセグメントは 2 つのエントリを保持しています。
システムは注釈情報 (名前が存在せず (namesz==0)、名前の長さが 0 (name[0]=='¥0') を予約していますが、現在、type を全く定義していません。他のすべての名前には、少なくとも 1 つの空ではない文字が存在しなければなりません。
非常に大きい配列の要素が初期化されると、その配列全体のデータがオブジェクトファイルに書き込まれます。再配置可能オブジェクトファイルまたは実行可能ファイルのサイズは、非常に大きくなることがあります。SHT_SUNW_move セクションは、このようなファイルを圧縮するために導入されています。
コンパイラまたはリンカーで作成されるオブジェクトには、部分的に初期化されたシンボルに対して移動セクションが存在することがあります。このセクションは、SHT_SUNW_move 型で定義されます。このセクションには、ELF32_Move/Elf64_Move 型の複数のエントリが存在します。これらのエントリは以下のように定義されます。
typedef struct { Elf32_Lword m_value; Elf32_Word m_info; Elf32_Word m_poffset; Elf32_Half m_repeat; Elf32_Half m_stride; } Elf32_Move; #define ELF32_M_SYM(info) ((info)>>8) #define ELF32_M_SIZE(info) ((unsigned char)(info)) #define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) typedef struct { Elf64_Lword m_value; Elf64_Xword m_info; Elf64_Xword m_poffset; Elf64_Half m_repeat; Elf64_Half m_stride; } Elf64_Move; #define ELF64_M_SYM(info) ((info)>>8) #define ELF64_M_SIZE(info) ((unsigned char)(info)) #define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) |
これは、シンボルからの相対オフセットです。
この構成要素は、移動を行わなければならないシンボルテーブルインデックスと、移動されるオブジェクトの大きさ (単位: バイト) を与えます。構成要素の下位 8 ビットは大きさを保持し、上位バイトはシンボルインデックスを保持します。大きさは、1、2、4、または 8 です。
この構成要素は、繰り返し回数です。
この構成要素は、1 つのオブジェクトを初期化するごとに飛び越えるオブジェクトの数を示します。この値が 0 の場合、初期化を m_repeat 回数連続して行うことを意味します。
この構成要素は、初期化値です。