いくつかのオブジェクトファイル制御構造は大きくなることがありますが、そのサイズは 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 識別で行われています。
オブジェクトファイルの種類を示します。次の種類が存在します。
表 7–3 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 までの値 (それぞれを含む) は、プロセッサ固有の方法で解釈されます。他の値は予約され、必要に応じて新しいオブジェクトファイルの種類に割り当てられます。
個々のファイルに必要なアーキテクチャを指定します。関連するアーキテクチャを、次の表に示します。
表 7–4 ELF 機種
名前 |
値 |
意味 |
---|---|---|
EM_NONE |
0 |
マシンが存在しない |
EM_SPARC |
2 |
SPARC |
EM_386 |
3 |
Intel 80386 |
EM_SPARC32PLUS |
18 |
Sun SPARC 32+ |
EM_SPARCV9 |
43 |
SPARC V9 |
他の値は予約され、必要に応じて新しい機種に割り当てられます (sys/elf.h を参照)。プロセッサ固有の ELF 名の識別には、機種名が使用されます。たとえば、表 7–5 で定義されたフラグでは、接頭辞 EF_ が使用されます。EM_XYZ マシンの WIDGET というフラグは、EF_XYZ_WIDGET と呼ばれます。
オブジェクトファイルのバージョンを示します。次のバージョンが存在します。
表 7–5 ELF バージョン
名前 |
値 |
意味 |
---|---|---|
EV_NONE |
0 |
無効なバージョン |
EV_CURRENT |
>=1 |
現在のバージョン |
値 1 は最初のファイル形式を示します。EV_CURRENT の値は、現在のバージョン番号を示すために必要に応じて変化します。
システムが制御を最初に渡す仮想アドレスを保持し、仮想アドレスが与えられると、プロセスが起動します。ファイルに関連するエントリポイントが存在しない場合、この構成要素は 0 を保持します。
プログラムヘッダーテーブルのファイルオフセットを保持します (単位: バイト)。ファイルにプログラムヘッダーテーブルが存在しない場合、この構成要素は 0 を保持します。
セクションヘッダーテーブルのファイルオフセットを保持します (単位: バイト)。ファイルにセクションヘッダーテーブルが存在しない場合、この構成要素は 0 を保持します。
ファイルに対応付けられたプロセッサ固有のフラグを保持します。フラグ名は、EF_machine「_flag」という形式をとります。x86 の場合、この構成要素はゼロになります。SPARC の場合のフラグを、次の表に示します。
表 7–6 SPARC: ELF フラグ
名前 |
値 |
意味 |
---|---|---|
EF_SPARC_EXT_MASK |
0xffff00 |
ベンダー拡張マスク |
EF_SPARC_32PLUS |
0x000100 |
V8+ 共通機能 |
EF_SPARC_SUN_US1 |
0x000200 |
Sun UltraSPARC™ 1 拡張 |
EF_SPARC_HAL_R1 |
0x000400 |
HAL R1 拡張 |
EF_SPARC_SUN_US3 |
0x000800 |
Sun UltraSPARC 3 拡張 |
EF_SPARCV9_MM |
0x3 |
メモリーモデルのマスク |
EF_SPARCV9_TSO |
0x0 |
トータルストアオーダリング (TSO) |
EF_SPARCV9_PSO |
0x1 |
パーシャルストアオーダリング (PSO) |
EF_SPARCV9_RMO |
0x2 |
リラックスメモリーオーダリング (RMO) |
ELF ヘッダーのサイズ (単位: バイト)。
ファイルのプログラムヘッダーテーブルの 1 つのエントリのサイズ (単位:バイト)。すべてのエントリは同じサイズです。
プログラムヘッダーテーブルのエントリ数。e_phentsize に e_phnum を掛けると、テーブルのサイズ (単位: バイト) が求められます。ファイルにプログラムヘッダーテーブルが存在しない場合、e_phnum は値 0 を保持します。
セクションヘッダーのサイズ (単位:バイト)。1 つのセクションヘッダーは、セクションヘッダーテーブルの 1 つのエントリです。すべてのエントリは同じサイズです。
セクションヘッダーテーブルのエントリ数。e_shentsize に e_shnum を掛けると、セクションヘッダーテーブルのサイズ (単位: バイト) が求められます。ファイルにセクションヘッダーテーブルが存在しない場合、e_shnum は値 0 を保持します。
セクションの数が SHN_LORESERVE (0xff00) 以上の場合、この構成要素の値は 0 となり、セクションヘッダーテーブルエントリの実際の数はセクションヘッダーの sh_size フィールドのインデックス 0 の位置に入っています。そうでない場合、当初のエントリの sh_size 構成要素には 0 が入っています。
セクション名文字列テーブルに対応するエントリのセクション ヘッダーテーブルインデックス。ファイルにセクション名文字列テーブルが存在しない場合、この構成要素は値 SHN_UNDEF を保持します。
セクション名文字列テーブルセクションのインデックスが SHN_LORESERVE (0xff00) 以上の場合、この構成要素の値は SHN_XINDEX (0xffff) となり、セクション名文字列テーブルセクションの実際のインデックスはセクションヘッダーの sh_link フィールドのインデックス 0 の位置に入っています。そうでない場合、当初のエントリの sh_link 構成要素には 0 が入っています。