リンカーとライブラリ

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

この章では、アセンブラとリンカーで生成されるオブジェクトファイルの実行可能リンク形式 (ELF) について説明します。オブジェクトファイルには、主に次の 3 つの種類があります。

この章の最初の節、「ファイル形式」では、オブジェクトファイルの形式、およびこの形式がプログラム作成にどのように関係しているかに焦点を当てています。次の節、「動的リンク」では、この形式がプログラムの読み込みにどのように関係しているかに焦点を当てています。

プログラム内からオブジェクトファイルを操作するには、ELF アクセスライブラリ libelf によって提供される関数を使用します。libelf の説明については、elf(3ELF) のマニュアルページを参照してください。libelf を使用するサンプルソースコードは、SUNWosdem パッケージに含まれており、/usr/demo/ELF ディレクトリの下に置かれています。

ファイル形式

オブジェクトファイルはプログラムのリンクと実行の両方に関係します。利便性と効率性のため、オブジェクトファイルの形式には、リンクと実行の異なる要求に合わせて、2 つの平行した見方があります。次の図にオブジェクトファイルの編成を示します。

図 7–1 オブジェクトファイル形式

オブジェクトファイル形式です。

ELF ヘッダーはオブジェクトファイルの先頭に存在し、ファイル編成を記述する「ロードマップ」を保持します。


注 –

ELF ヘッダーの位置のみがファイル内で固定されています。ELF 形式には柔軟性があるため、ヘッダーテーブル、セクション、およびセグメントの順序は特に決まっていません。この図に示したのは、Solaris OS で使用される典型的なレイアウトです。


「セクション」は、 ELF ファイル内で処理可能な最小単位 (これ以上分割できない単位) です。「セグメント」は、セクションの集合です。セグメントは、exec(2) または実行時リンカーでメモリーイメージに対応付けできる最小単位です。

セクションは、リンクの観点から見たオブジェクトファイルの情報の大部分を保持します。このデータには、命令、データ、シンボルテーブル、再配置情報などが含まれます。セクションに関しては、この章の前半で説明します。セグメントとプログラムの実行の観点から見たファイルの構造に関しては、この章の後半で説明します。

プログラムヘッダーテーブル (存在する場合) は、システムにプロセスイメージの作成方法を通知します。プロセスイメージの生成に使用されるファイル (実行可能ファイルと共有オブジェクト) には、プログラムヘッダーテーブルが存在する必要があります。再配置可能オブジェクトでは、プログラムヘッダーテーブルは必要ありません。

セクションヘッダーテーブルには、ファイルのセクションを記述する情報が入っています。セクションヘッダーテーブルには各セクションのエントリが存在します。各エントリは、セクション名、セクションサイズなどの情報が含まれます。リンク編集で使用されるファイルには、セクションヘッダーテーブルが存在しなければなりません。

データ表現

オブジェクトファイルの形式は、8 ビットバイト、32 ビットアーキテクチャー、および 64 ビットアーキテクチャーを持つさまざまなプロセッサをサポートしています。しかしながら、データ表現は、より大きな、またはより小さなアーキテクチャーに拡張できるように意図されています。表 7–1表 7–2 に、32 ビットデータタイプと 64 ビットデータタイプの一覧を示します。

オブジェクトファイルは、いくつかの制御データをマシンに依存しない形式で表現します。この形式は、オブジェクトファイルの共通の識別および解釈を規定します。オブジェクトファイルの残りのデータは、このオブジェクトファイルが作成されたマシンとは関係なく、対象となるプロセッサ用に符号化されています。

表 7–1 ELF 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 ELF 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;
e_ident

先頭のバイト列は、オブジェクトファイルであることを示す印です。これらのバイトには、機種に依存しない、ファイルの内容を復号化または解釈するためのデータが入ります。詳細な説明は、「ELF 識別」に記載されています。

e_type

オブジェクトファイルの種類を示します。次の種類が存在します。

名前 

値 

意味 

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 までの値 (それぞれを含む) は、プロセッサ固有のセマンティクスのために予約されています。ほかの値は、将来の使用に備えて保留されます。

e_machine

個々のファイルに必要なアーキテクチャーを指定します。関連するアーキテクチャーを、次の表に示します。

名前 

値 

意味 

EM_NONE

0

マシンが存在しない 

EM_SPARC

2

SPARC 

EM_386

3

Intel 80386 

EM_SPARC32PLUS

18

Sun SPARC 32+ 

EM_SPARCV9

43

SPARC V9 

EM_AMD64

62

AMD 64 

ほかの値は、将来の使用に備えて保留されます。プロセッサ固有の ELF 名の識別には、機種名が使用されます。たとえば、e_flags に定義されるフラグでは、接頭辞 EF_ が使用されます。EM_XYZ マシンの WIDGET というフラグは、EF_XYZ_WIDGET と呼ばれます。

e_version

オブジェクトファイルのバージョンを示します。次のバージョンが存在します。

名前 

値 

意味 

EV_NONE

0

無効バージョン 

EV_CURRENT

>=1

現在のバージョン 

値 1 は最初のファイル形式を示し、EV_CURRENT の値は、現在のバージョン番号を示すために必要に応じて変化します。

e_entry

システムが制御を最初に渡す仮想アドレスを保持し、仮想アドレスが与えられると、プロセスが起動します。ファイルに関連するエントリポイントが存在しない場合、このメンバーは 0 を保持します。

e_phoff

プログラムヘッダーテーブルのファイルオフセットを保持します (単位: バイト)。ファイルにプログラムヘッダーテーブルが存在しない場合、このメンバーは 0 を保持します。

e_shoff

セクションヘッダーテーブルのファイルオフセットを保持します (単位: バイト)。ファイルにセクションヘッダーテーブルが存在しない場合、このメンバーは 0 を保持します。

e_flags

ファイルに対応付けられたプロセッサ固有のフラグを保持します。フラグ名は、EF_machine「_flag」という形式をとります。このメンバーは、現在 x86 に対しては 0 です。SPARC の場合のフラグを、次の表に示します。

名前 

値 

意味 

EF_SPARC_EXT_MASK

0xffff00

ベンダー拡張マスク 

EF_SPARC_32PLUS

0x000100

V8+ 共通機能

EF_SPARC_SUN_US1

0x000200

Sun UltraSPARCTM 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) 

e_ehsize

ELF ヘッダーのサイズ (単位: バイト)。

e_phentsize

ファイルのプログラムヘッダーテーブルの 1 つのエントリのサイズ (単位:バイト)。すべてのエントリは同じサイズです。

e_phnum

プログラムヘッダーテーブルのエントリ数。e_phentsizee_phnum を掛けると、テーブルのサイズ (単位: バイト) が求められます。ファイルにプログラムヘッダーテーブルが存在しない場合、e_phnum は値 0 を保持します。

プログラムヘッダーの数が PN_XNUM (0xffff) 以上である場合、このメンバーは値 PN_XNUM (0xffff) を保持します。プログラムヘッダーテーブルエントリの実際の数は、インデックス 0 のセクションヘッダーの sh_info フィールドに含まれます。そうでない場合、初期セクションヘッダーエントリの sh_info メンバーには値 0 が入っています。表 7–6 および表 7–7 を参照してください。

e_shentsize

セクションヘッダーのサイズ (単位:バイト)。1 つのセクションヘッダーは、セクションヘッダーテーブルの 1 つのエントリです。すべてのエントリは同じサイズです。

e_shnum

セクションヘッダーテーブルのエントリ数。e_shentsizee_shnum を掛けると、セクションヘッダーテーブルのサイズ (単位: バイト) が求められます。ファイルにセクションヘッダーテーブルが存在しない場合、e_shnum は値 0 を保持します。

セクション数が SHN_LORESERVE (0xff00) 以上の場合、e_shnum の値は 0 になります。セクションヘッダーテーブルエントリの実際の数は、インデックス 0sh_size フィールドに含まれます。そうでない場合、初期セクションヘッダーエントリの sh_size メンバーには値 0 が入っています。表 7–6 および表 7–7 を参照してください。

e_shstrndx

セクション名文字列テーブルに対応するエントリのセクション ヘッダーテーブルインデックス。ファイルにセクション名文字列テーブルが存在しない場合、このメンバーは値 SHN_UNDEF を保持します。

セクション名文字列テーブルセクションのインデックスが SHN_LORESERVE (0xff00) 以上の場合、このメンバーの値は SHN_XINDEX (0xffff) となり、セクション名文字列テーブルセクションの実際のインデックスはインデックス 0 のセクションヘッダーの sh_link フィールドに入っています。そうでない場合、初期セクションヘッダーエントリの sh_link メンバーには値 0 が入っています。表 7–6 および表 7–7 を参照してください。

ELF 識別

ELF はオブジェクトファイルの枠組みを提供し、複数のプロセッサ、複数のデータ符号化、複数のクラスのマシンをサポートします。このオブジェクトファイルファミリをサポートするため、ファイルの初期バイトによりファイルの解釈方法が指定されます。これらの初期バイトは、問い合わせが行われるプロセッサにも、ファイルのほかの内容にも依存しません。

ELF ヘッダーおよびオブジェクトファイル の初期バイトは、e_ident メンバーに一致します。

表 7–3 ELF 識別インデックス

名前 

値 

目的 

EI_MAG0

0

ファイルの識別 

EI_MAG1

1

ファイルの識別 

EI_MAG2

2

ファイルの識別 

EI_MAG3

3

ファイルの識別 

EI_CLASS

4

ファイルのクラス 

EI_DATA

5

データの符号化 

EI_VERSION

6

ファイルのバージョン 

EI_OSABI

7

オペレーティングシステム / ABI の識別

EI_ABIVERSION

8

ABI のバージョン

EI_PAD

9

パッドバイトの開始 

EI_NIDENT

16

e_ident[] のサイズ

次のインデックスは、次の値を保持するバイトにアクセスします。

EI_MAG0 - EI_MAG3

ファイルを ELF オブジェクトファイルとして識別する 4 バイトの「マジックナンバー」。次の表を参照してください。

名前 

値 

位置 

ELFMAG0

0x7f

e_ident[EI_MAG0]

ELFMAG1

'E'

e_ident[EI_MAG1]

ELFMAG2

'L'

e_ident[EI_MAG2]

ELFMAG3

'F'

e_ident[EI_MAG3]

EI_CLASS

バイト e_ident[EI_CLASS] は、ファイルのクラスまたは容量を示します。次の表にファイルのクラスを示します。

名前 

値 

意味 

ELFCLASSNONE

0

無効なクラス 

ELFCLASS32

1

32 ビットオブジェクト 

ELFCLASS64

2

64 ビットオブジェクト 

ファイル形式は、最大マシンのサイズを最小マシンに押しつけることなしにさまざまなサイズのマシン間で互換性が維持されるように設計されています。ファイルのクラスは、オブジェクトファイルコンテナのデータ構造によって使用される基本タイプを定義します。オブジェクトファイルセクションに含まれるデータは、異なるプログラミングモデルに準拠する場合があります。

クラス ELFCLASS32 は、4 ギガバイトまでのファイルと仮想アドレス空間が存在するマシンをサポートします。このクラスは、表 7–1 で定義される基本タイプを使用します。

クラス ELFCLASS64 は、64 ビット SPARC や x64 などの 64 ビットアーキテクチャー用に予約されています。このクラスは、表 7–2 で定義される基本タイプを使用します。

EI_DATA

バイト e_ident[EI_DATA] は、オブジェクトファイルのプロセッサ固有のデータの符号化を指定します (次の表を参照)。

名前 

値 

意味 

ELFDATANONE

0

無効な符号化 

ELFDATA2LSB

1

図 7–2 を参照してください。

ELFDATA2MSB

2

図 7–3 を参照してください。

これらの符号化の詳細は、「データの符号化」で説明します。ほかの値は、将来の使用に備えて保留されます。

EI_VERSION

バイト e_ident[EI_VERSION] は、ELF ヘッダーバージョン番号を指定します。現在この値は、EV_CURRENT でなければなりません。

EI_OSABI

バイト e_ident[EI_OSABI] は、オブジェクトのターゲット先となる ABI とともにオペレーティングシステムを識別します。ほかの ELF 構造体内のフィールドの中には、オペレーティングシステム特有または ABI 特有の意味を持つフラグおよび値を保持するものがあります。これらのフィールドの解釈は、このバイトの値によって決定されます。

EI_ABIVERSION

バイト e_ident[EI_ABIVERSION] は、オブジェクトのターゲット先となる ABI のバージョンを識別します。このフィールドは、ABI の互換性のないバージョンを識別するために使用します。このバージョン番号の解釈は、EI_OSABI フィールドで識別される ABI によって異なります。プロセッサについて EI_OSABI フィールドに値が何も指定されていない場合、または EI_OSABI バイトの特定の値によって決定される ABI についてバージョンの値が何も指定されていない場合は、指定なしを示すものとして値 0 が使用されます。

EI_PAD

この値は、e_ident の使用されていないバイトの先頭を示します。これらのバイトは保留され、0 に設定されます。オブジェクトファイルを読み取るプログラムは、これらの値を無視します。

データの符号化

ファイルのデータ符号化方式は、ファイルの整数タイプを解釈する方法を指定します。クラス ELFCLASS32 のファイルおよびクラス ELFCLASS64 のファイルは、1、2、4、および 8 バイトを占める整数を使用して、オフセット、アドレス、およびその他の情報を表現します。定義されている符号化方式の下では、オブジェクトは次の図の説明のように表されます。バイト番号は、左上隅に示されています。

ELFDATA2LSB を符号化すると、最下位バイトが最低位アドレスを占める 2 の補数値が指定されます。この符号化は、一般的にはよく「リトルエンディアン」と呼ばれます。

図 7–2 データの符号化方法 ELFDATA2LSB

ELFDATA2LSB データの符号化方法。

ELFDATA2MSB を符号化すると、最上位バイトが最低位アドレスを占める 2 の補数値が指定されます。この符号化は、一般的にはよく「ビッグエンディアン」と呼ばれます。

図 7–3 データの符号化方法 ELFDATA2MSB

ELFDATA2MSB データの符号化方法。

セクション

オブジェクトファイルのセクションヘッダーテーブルを使用すると、ファイルのセクションすべてを見つけ出すことができます。セクションヘッダーテーブルは、Elf32_Shdr 構造体または Elf64_Shdr 構造体の配列です。セクションヘッダーテーブルインデックスは、この配列への添字です。ELF ヘッダーの e_shoff メンバーは、ファイルの先頭からセクションヘッダーテーブルまでのバイトオフセットを示します。e_shnum メンバーは、セクションヘッダーテーブルに含まれるエントリ数を示します。e_shentsize メンバーは、各エントリのバイト単位の大きさを示します。

セクション数が SHN_LORESERVE (0xff00) 以上の場合、e_shnum の値は SHN_UNDEF (0) になります。セクションヘッダーテーブルエントリの実際の数は、インデックス 0sh_size フィールドに含まれます。そうでない場合、初期エントリの sh_size メンバーには値 0 が入っています。

セクションヘッダーテーブルインデックスの中には、インデックスサイズが制限されている文脈で予約されているものがあります。たとえば、シンボルテーブルエントリの st_shndx メンバー、 ELF ヘッダーの e_shnum メンバーと e_shstrndx メンバーなどがそうです。このような文脈では、予約値はオブジェクトファイル内の実際のセクションを示しません。また、このような文脈では、エスケープ値は、実際のセクションインデックスがどこかもっと大きなフィールド内に存在することを示します。

表 7–4 ELF セクションの特殊インデックス

名前 

値 

SHN_UNDEF

0

SHN_LORESERVE

0xff00

SHN_LOPROC

0xff00

SHN_BEFORE

0xff00

SHN_AFTER

0xff01

SHN_AMD64_LCOMMON

0xff02

SHN_HIPROC

0xff1f

SHN_LOOS

0xff20

SHN_LOSUNW

0xff3f

SHN_SUNW_IGNORE

0xff3f

SHN_HISUNW

0xff3f

SHN_HIOS

0xff3f

SHN_ABS

0xfff1

SHN_COMMON

0xfff2

SHN_XINDEX

0xffff

SHN_HIRESERVE

0xffff


注 –

インデックス 0 は未定義値として予約されますが、セクションヘッダーテーブルにはインデックス 0 のエントリが存在します。つまり、ELF ヘッダーの e_shnum メンバーが、ファイルのセクションヘッダーテーブルに 6 つのエントリが存在することを示している場合、これら 6 つのエントリにはインデックス 0 から 5 までが与えられます。先頭のエントリの内容は、この項の末尾に記述します。


SHN_UNDEF

未定義、存在しない、無関係など、無意味なセクション参照。たとえば、セクション番号 SHN_UNDEF に関して「定義された」シンボルは、未定義シンボルです。

SHN_LORESERVE

予約済みインデックスの範囲の下限。

SHN_LOPROC - SHN_HIPROC

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

SHN_LOOS - SHN_HIOS

この両端を含む範囲の値は、オペレーティングシステム固有のセマンティクスのために予約されています。

SHN_LOSUNW - SHN_HISUNW

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

SHN_SUNW_IGNORE

このセクションインデックスは、再配置可能オブジェクト内の一時的なシンボル定義を提供します。dtrace(1M) の内部使用のため予約されています。

SHN_BEFORE, SHN_AFTER

SHF_LINK_ORDER および SHF_ORDERED セクションフラグとともに先頭および末尾のセクションの順序付けを行います。表 7–8 を参照してください。

SHN_AMD64_LCOMMON

x64 固有の共通ブロックラベル。このラベルは SHN_COMMON に似ていますが、大規模な共通ブロックの識別をサポートする点が異なります。

SHN_ABS

対応する参照の絶対値。たとえば、セクション番号 SHN_ABS からの相対で定義されたシンボルは絶対値をとり、再配置の影響を受けません。

SHN_COMMON

このセクションに対して相対的に定義されるシンボルは、FORTRAN の COMMON や割り当てられていない C 外部変数などの共通シンボルです。これらのシンボルは、一時的シンボルと呼ばれることもあります。

SHN_XINDEX

実際のセクションヘッダーインデックスが大きすぎて格納先のフィールドに入りきらないことを示すエスケープ値。ヘッダーセクションインデックスは、このインデックスが出現する構造体に固有の別の場所に存在します。

SHN_HIRESERVE

予約済みインデックスの範囲の上限。システムは、SHN_LORESERVE から SHN_HIRESERVE までのインデックスを予約します。値は、セクションヘッダーテーブルを参照しません。セクションヘッダーテーブルには予約されているインデックスのエントリは存在しません。

セクションには、ELF ヘッダー、プログラムヘッダーテーブル、セクションヘッダーテーブルを除く、オブジェクトファイルのすべての情報が存在します。また、オブジェクトファイルのセクションは次の条件を満たします。

セクションヘッダーの構造体は、次のとおりです。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;
sh_name

セクション名。このメンバー値はセクションヘッダーの文字列テーブルセクションへのインデックスで、ヌル文字で終わる文字列の位置を示します。セクション名とその説明は、表 7–10 を参照してください。

sh_type

セクションの内容とセマンティクスを分類します。セクションの種類とその説明は、表 7–5 を参照してください。

sh_flags

セクションは、さまざまな属性を記述する 1 ビットフラグをサポートします。フラグの定義は、表 7–8 を参照してください。

sh_addr

セクションがプロセスのメモリーイメージに現れる場合、このメンバーはセクションの先頭バイトが存在しなければならないアドレスを与えます。セクションがプロセスのメモリーイメージに現れない場合、このメンバーには 0 が存在します。

sh_offset

ファイルの先頭からセクションの先頭バイトまでのバイトオフセット。SHT_NOBITS 型のセクションの場合はファイル内のスペースを占めないため、このメンバーは、ファイル内の概念的なオフセットを示します。

sh_size

セクションのサイズ (バイト)。セクションのタイプが SHT_NOBITS でないかぎり、セクションはファイルの sh_size バイトを占めます。タイプが SHT_NOBITS のセクションは、0 以外のサイズをとることがありますが、ファイルのスペースは占めません。

sh_link

セクションヘッダーテーブルのインデックスリンク。このリンクの解釈は、セクションのタイプに依存します。値については、表 7–9 を参照してください。

sh_info

追加情報。情報の解釈は、セクションのタイプに依存します。値については、表 7–9 を参照してください。このセクションヘッダーの sh_flags フィールドに属性 SHF_INFO_LINK が含まれている場合、このメンバーはセクションヘッダーテーブルインデックスを表します。

sh_addralign

いくつかのセクションには、アドレス整列制約が存在します。たとえば、あるセクションが 2 語で構成されるデータを保持している場合、システムはそのセクション全体に対して 2 語単位の整列を保証しなければなりません。この場合、sh_addr の値は、sh_addralign の値を法として 0 でなければなりません。現在、0、および 2 の非負整数累乗のみが許可されています。値 01 は、セクションに整列制約が存在しないことを意味します。

sh_entsize

いくつかのセクションは、サイズが一定のエントリのテーブル (シンボルテーブルなど) を保持します。このようなセクションに対してこのメンバーは、各エントリのサイズ (単位: バイト) を与えます。サイズが一定のエントリのテーブルをセクションが保持しない場合、このメンバーには 0 が格納されます。

セクションヘッダーの sh_type メンバーは、次の表に示すようにこのセクションのセマンティクスを示します。

表 7–5 ELF セクションタイプ、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_INIT_ARRAY

14

SHT_FINI_ARRAY

15

SHT_PREINIT_ARRAY

16

SHT_GROUP

17

SHT_SYMTAB_SHNDX

18

SHT_LOOS

0x60000000

SHT_LOSUNW

0x6ffffff4

SHT_SUNW_dof

0x6ffffff4

SHT_SUNW_cap

0x6ffffff5

SHT_SUNW_SIGNATURE

0x6ffffff6

SHT_SUNW_ANNOTATE

0x6ffffff7

SHT_SUNW_DEBUGSTR

0x6ffffff8

SHT_SUNW_DEBUG

0x6ffffff9

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_HISUNW

0x6fffffff

SHT_HIOS

0x6fffffff

SHT_LOPROC

0x70000000

SHT_SPARC_GOTDATA

0x70000000

SHT_AMD64_UNWIND

0x70000001

SHT_HIPROC

0x7fffffff

SHT_LOUSER

0x80000000

SHT_HIUSER

0xffffffff

SHT_NULL

セクションヘッダーが無効であることを示します。このセクションヘッダーには、関連付けられているセクションは存在しません。セクションヘッダーのほかのメンバーの値は不定です。

SHT_PROGBITS

プログラムによって定義された情報を示します。その形式や意味はすべて、プログラムによって決定されます。

SHT_SYMTABSHT_DYNSYM

シンボルテーブルを示します。一般に、SHT_SYMTAB セクションはリンク編集に関するシンボルを示します。このテーブルには完全なシンボルテーブルとして、動的リンクに不要な多くのシンボルが存在することがあります。また、オブジェクトファイルには SHT_DYNSYM セクション (動的リンクシンボルの最小セットを保持して領域を節約している) が存在することがあります。

詳細は、「シンボルテーブルセクション」を参照してください。

SHT_STRTABSHT_DYNSTR

文字列テーブルを示します。オブジェクトファイルには、複数の文字列テーブルセクションを指定できます。詳細は、「文字列テーブルセクション」を参照してください。

SHT_RELA

32 ビットクラスのオブジェクトファイル用のタイプ Elf32_Rela など、明示的加数を含む再配置エントリを示します。オブジェクトファイルには、複数の再配置セクションを指定できます。詳細は、「再配置セクション」を参照し てください。

SHT_HASH

シンボルハッシュテーブルを示します。動的にリンクされたオブジェクトファイルには、シンボルハッシュテーブルが存在しなければなりません。現在、オブジェクトファイルにはハッシュテーブルは 1 つしか存在できませんが、この制約は将来、緩和されるかもしれません。詳細は、「ハッシュテーブルセクション」を参照してください。

SHT_DYNAMIC

動的リンク処理用の情報を示します。現在、オブジェクトファイルには動的セクションを 1 つだけ含めることができます。詳細は、「動的セクション」を参照してください。

SHT_NOTE

ファイルに何らかの方法で付加すべき情報を示します。詳細は、「注釈セクション」を参照してください。

SHT_NOBITS

ファイル内の領域を占有しないセクションを示します。このセクションは、その他の点では SHT_PROGBITS に似ています。このセクションにはデータは存在しませんが、sh_offset メンバーには概念上のファイルオフセットが存在します。

SHT_REL

32 ビットクラスのオブジェクトファイル用のタイプ Elf32_Rel など、明示的加数を含まない再配置エントリを示します。オブジェクトファイルには、複数の再配置セクションを指定できます。詳細は、「再配置セクション」を参照し てください。

SHT_SHLIB

セマンティクスが定義されていない予約済みセクションを示します。この型のセクションが存在するプログラムは、ABI に準拠しません。

SHT_INIT_ARRAY

初期設定関数へのポインタの配列を含むセクションを示します。配列内の各ポインタは、void を戻り値とする、パラメータを持たないプロシージャーと見なされます。詳細は、「初期設定および終了セクション」を参照してください。

SHT_FINI_ARRAY

終了関数へのポインタの配列を含むセクションを示します。配列内の各ポインタは、void を戻り値とする、パラメータを持たないプロシージャーと見なされます。詳細は、「初期設定および終了セクション」を参照してください。

SHT_PREINIT_ARRAY

ほかのすべての初期設定関数の前に呼び出される関数へのポインタの配列を含むセクションを示します。配列内の各ポインタは、void を戻り値とする、パラメータを持たないプロシージャーと見なされます。詳細は、「初期設定および終了セクション」を参照してください。

SHT_GROUP

セクショングループを示します。セクショングループとは、関連する一連のセクションであり、リンカーは 1 つの単位として扱う必要があります。タイプが SHT_GROUP であるセクションは、再配置可能オブジェクト内にしか存在できません。詳細は、「グループセクション」を参照してください。

SHT_SYMTAB_SHNDX

拡張されたセクションインデックスが入ったセクション (シンボルテーブルに関連 付けられている) を示します。シンボルテーブルによって参照されているセクションヘッダーインデックスのいずれかにエスケープ値 SHN_XINDEX が含まれる場合は、関連する SHT_SYMTAB_SHNDX が必要です。

SHT_SYMTAB_SHNDX セクションは、Elf32_Word 値の配列です。この配列には、関連するシンボルテーブルエントリごとに 1 つのエントリが存在します。これらの値は、シンボルテーブルエントリが定義されているセクションヘッダーインデックスを示します。一致する Elf32_Word に実際のセクションヘッダーインデックスが含まれるのは、対応するシンボルテーブルエントリの st_shndx フィールドにエスケープ値 SHN_XINDEX が含まれる場合だけです。そうでない場合、エントリは必ず SHN_UNDEF (0) です。

SHT_LOOSSHT_HIOS

この両端を含む範囲の値は、オペレーティングシステム固有のセマンティクスのために予約されています。

SHT_LOSUNWSHT_HISUNW

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

SHT_SUNW_dof

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

SHT_SUNW_cap

ハードウェアとソフトウェアの機能要件を指定します。詳細は、「ハードウェアおよびソフトウェア機能に関するセクション」を参照してください。

SHT_SUNW_SIGNATURE

モジュール検証用の署名を示します。

SHT_SUNW_ANNOTATE

注釈セクションの処理は、デフォルトのセクション処理規則のすべてに従います。唯一の例外は、注釈セクションが割り当て不可能なメモリー内に存在する場合に発生します。セクションのヘッダーフラグ SHF_ALLOC が設定されていないと、 リンカーは、このセクションに対する未対応の再配置をすべて黙って無視します。

SHT_SUNW_DEBUGSTRSHT_SUNW_DEBUG

デバッグ情報を示します。このタイプのセクションは、リンカーの -s オプションを使用するか、あるいはリンク編集後に strip(1) を使用して、オブジェクトから取り除くことができます。

SHT_SUNW_move

部分的に初期設定されたシンボルを処理するためのデータを示します。詳細は、「移動セクション」を参照してください。

SHT_SUNW_COMDAT

同一データの複数のコピーを単一のコピーに低減することを可能にするセクションを示します。詳細は、「「COMDAT」セクション」を参照してください。

SHT_SUNW_syminfo

追加のシンボル情報を示します。詳細は、「Syminfo テーブルセクション」を参照してください。

SHT_SUNW_verdef

このファイルで定義された細粒度のバージョンを示します。詳細は、「バージョン定義セクション」を参照してください。

SHT_SUNW_verneed

このファイルが必要とする細粒度の依存関係を示します。詳細は、「バージョン依存セクション」を参照してください。

SHT_SUNW_versym

シンボルと、ファイルが提供するバージョン定義との関係を記述したテーブルを示します。詳細は、「バージョンシンボルセクション」を参照してください。

SHT_LOPROC - SHT_HIPROC

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

SHT_SPARC_GOTDATA

GOT からの相対アドレスを使って参照される、SPARC 固有のデータを示します。つまり、シンボル _GLOBAL_OFFSET_TABLE_ に割り当てられたアドレスに対する相対的なオフセットです。64 ビット SPARC の場合、このセクション内のデータは、リンク編集時に GOT アドレスの {+-} 2^32 バイト内の場所に結合されなければなりません。

SHT_AMD64_UNWIND

スタックを巻き戻すための巻き戻し (unwind) 関数テーブルエントリを含む、x64 固有のデータを示します。

SHT_LOUSER

アプリケーションプログラム用として予約されているインデックスの範囲の下限を指定します。

SHT_HIUSER

アプリケーションプログラム用として予約されているインデックスの範囲の上限を指定します。SHT_LOUSER から SHT_HIUSER までのセクション型は、現在の、または将来のシステム定義セクション型と競合することなくアプリケーションで使用できます。

ほかのセクション型の値は、保留されています。先に述べたとおり、そのインデックスが未定義セクション参照を示している場合でも、インデックス 0 (SHN_UNDEF) のセクションヘッダーは存在します。その値は次の表のとおりです。

表 7–6 ELF セクションヘッダーテーブルエントリ: インデックス 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

エントリが存在しない 

セクションまたはプログラムヘッダーの数が ELF ヘッダーデータサイズを超えた場合、セクションヘッダー 0 の構成要素を使って拡張 ELF ヘッダー属性が定義されます。その値は次の表のとおりです。

表 7–7 ELF 拡張セクションヘッダーテーブルエントリ: インデックス 0

名前 

値 

注意 

sh_name

0

名前が存在しない 

sh_type

SHT_NULL

使用されない 

sh_flags

0

フラグが存在しない 

sh_addr

0

アドレスが存在しない 

sh_offset

0

ファイルオフセットが存在しない 

sh_size

e_shnum

セクションヘッダーテーブルのエントリ数 

sh_link

e_shstrndx

セクション名文字列テーブルに対応するエントリのセクション ヘッダーインデックス 

sh_info

e_phnum

プログラムヘッダーテーブルのエントリ数 

sh_addralign

0

整列が存在しない 

sh_entsize

0

エントリが存在しない 

セクションヘッダーの sh_flags メンバーは、セクションの属性を記述する 1 ビットフラグを保持します。

表 7–8 ELF セクションの属性フラグ

名前 

値 

SHF_WRITE

0x1

SHF_ALLOC

0x2

SHF_EXECINSTR

0x4

SHF_MERGE

0x10

SHF_STRINGS

0x20

SHF_INFO_LINK

0x40

SHF_LINK_ORDER

0x80

SHF_OS_NONCONFORMING

0x100

SHF_GROUP

0x200

SHF_TLS

0x400

SHF_MASKOS

0x0ff00000

SHF_AMD64_LARGE

0x10000000

SHF_ORDERED

0x40000000

SHF_EXCLUDE

0x80000000

SHF_MASKPROC

0xf0000000

sh_flags にフラグビットが設定されると、属性がセクションに対して「オン」になります。設定されない場合は、属性が「オフ」になるか、または適用されません。定義されていない属性は保留され、0 に設定されています。

SHF_WRITE

プロセス実行中に書き込み可能にすべきセクションを示します。

SHF_ALLOC

プロセス実行中にメモリーを占有するセクションを示します。いくつかの制御セクションは、オブジェクトファイルのメモリーイメージに存在しません。この属性は、これらのセクションに対してオフです。

SHF_EXECINSTR

実行可能なマシン命令を含むセクションを示します。

SHF_MERGE

マージして重複をなくすことの可能なデータを含むセクションを示します。同時に SHF_STRINGS フラグが設定されていないかぎり、このセクション内のデータ要素は統一されたサイズになります。各要素のサイズは、セクションヘッダーの sh_entsize フィールドで指定されます。同時に SHF_STRINGS フラグも設定されている場合は、データ要素はヌル文字で終わる文字列で構成されています。各文字のサイズは、セクションヘッダーの sh_entsize フィールドで指定されます。

SHF_STRINGS

ヌル文字で終わっている文字列で構成されるセクションを示します。各文字のサイズは、セクションヘッダーの sh_entsize フィールドで指定されます。

SHF_INFO_LINK

このセクションヘッダーの sh_info フィールドには、セクションヘッダーテーブルのインデックスが格納されます。

SHF_LINK_ORDER

このセクションは、リンカーに特別な順序の要求を追加します。この要求は、このセクションのヘッダーの sh_link フィールドが別のセクション (リンク先のセクション) を参照する場合に適用されます。このセクションを出力ファイル内のほかのセクションと結合する場合、結合対象セクションと同じ相対的な順序で現われます。同様に、リンクされるセクションは、それが結合されるセクションに現われます。

特殊な sh_link 値である SHN_BEFORE および SHN_AFTER (表 7–4 を参照) は、順序付けされるセット内のほかのすべてのセクションに対して、ソートされたセクションがそれぞれ前に付くまたは後に付くことを示します。順序付けの対象となるセクションの複数にこれらの特殊値の 1 つが存在する場合、入力ファイルが指定された順序は保存されます。

このフラグを使用する場合の典型的なものとして、アドレスの順序でテキストまたはデータセクションを参照するテーブルを構築する場合があります。

sh_link 順序付け情報が存在しない場合、出力ファイルの 1 つのセクション内にまとめられた単一入力ファイルからのセクションは、連続的になります。これらのセクションの相対順序付けは、入力ファイル内のセクションの相対順序付けと同じになります。複数の入力ファイルからの場合は、リンクコマンドで指定された順序になります。

SHF_OS_NONCONFORMING

このセクションは、不適切な動作を避けるために、標準のリンク処理規則に含まれない OS 固有の特殊処理を必要とします。このセクションが、これらのフィールドに対して sh_type 値を持つか、OS 固有の範囲内にある sh_flags ビットを含み、かつリンカーがこれらの値を認識しない場合は、このセクションを含むオブジェクトファイルは拒否され、エラーが出力されます。

SHF_GROUP

このセクションは、セクショングループのメンバー (おそらく唯一のメンバー) です。このセクションは、タイプ SHT_GROUP のセクションに参照されなければなりません。SHF_GROUP フラグは、再配置可能オブジェクト内に含まれるセクションに対してしか設定できません。詳細は、「グループセクション」を参照してください。

SHF_TLS

このセクションには、スレッド固有領域が格納されます。プロセス内の各スレッドは、このデータのインスタンスをそれぞれ別個に持ちます。詳細は、第 8 章スレッド固有領域 (TLS)を参照してください。

SHF_MASKOS

このマスクに含まれるビットはすべて、オペレーティングシステム固有のセマンティクスのために予約されています。

SHF_AMD64_LARGE

x64 用のデフォルトコンパイルモデルで使用できるのは、32 ビットのディスプレイスメントだけです。このディスプレイスメントでは、セクションのサイズ (最終的にはセグメントのサイズ) が 2G バイトに制限されます。この属性フラグは、2G バイトを超えるデータを格納できるセクションを識別します。このフラグを使えば、異なるコードモデルを使用するオブジェクトファイルのリンク処理を行えます。

SHF_AMD64_LARGE 属性フラグを含まない x64 オブジェクトファイルセクションは、小規模コードモデルを使用するオブジェクトから自由に参照できます。このフラグを含むセクションは、それよりも規模の大きいコードモデルを使用するオブジェクトからしか参照できません。たとえば、x64 中規模コードモデルのオブジェクトは、この属性フラグを含むセクション内のデータとこの属性フラグを含まないセクション内のデータを参照できます。ところが、x64 小規模コードモデルのオブジェクトは、このフラグを含まないセクション内のデータしか参照できません。

SHF_ORDERED

このセクションは、同じ型のほかのセクションと順序付けられます。順序付けられるセクションは、sh_link エントリでポイントされるセクション内で結合されます。順序付けられるセクションの sh_link エントリは、自身を指し示すことがあります。

順序付けられるセクションの sh_info エントリが同一入力ファイル内の有効セクションの場合、順序付けられるセクションは、sh_info エントリでポイントされるセクションの出力ファイル内の相対順序付けに基づいて整列されます。

特殊な sh_info 値である SHN_BEFORE および SHN_AFTER (表 7–4 を参照) は、順序付けされるセット内のほかのすべてのセクションに対して、ソートされたセクションがそれぞれ前に付くまたは後に付くことを示します。順序付けの対象となるセクションの複数にこれらの特殊値の 1 つが存在する場合、入力ファイルが指定された順序は保存されます。

sh_info 順序付け情報が存在しない場合、出力ファイルの 1 つのセクション内にまとめられた単一入力ファイルからのセクションは、連続的になります。これらのセクションの相対順序付けは、入力ファイル内で表示されるセクションの相対順序付けと同じになります。複数の入力ファイルからの場合は、リンクコマンドで指定された順序になります。

SHF_EXCLUDE

このセクションは、実行可能オブジェクトまたは共有オブジェクトのリンク編集への入力から除外されます。このフラグは、SHF_ALLOC フラグが設定されている場合、またはセクションに対する参照が存在する場合、無視されます。

SHF_MASKPROC

このマスクに含まれるビットはすべて、プロセッサ固有のセマンティクスのために予約されています。

セクションヘッダーの 2 つのメンバー sh_linksh_info は、セクション型に従って特殊な情報を保持します。

表 7–9 ELF sh_linksh_info の解釈

sh_type

sh_link

sh_info

SHT_DYNAMIC

関連付けられている文字列テーブルのセクションヘッダーインデックス。 

0

SHT_HASH

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

0

SHT_REL

SHT_RELA

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

sh_flags メンバーに SHF_INFO_LINK フラグが含まれている場合は再配置が適用されるセクションのセクションヘッダーインデックス、それ以外の場合は 0表 7–10「再配置セクション」も参照してください。

SHT_SYMTAB

SHT_DYNSYM

関連付けられている文字列テーブルのセクションヘッダーインデックス。 

最後の局所シンボルのシンボルテーブルインデックス STB_LOCAL より 1 大きい。

SHT_GROUP

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

関連付けられているシンボルテーブル内のエントリの、シンボルテーブルインデックス。指定されたシンボルテーブルエントリの名前は、そのセクショングループのシグニチャを提供します。 

SHT_SYMTAB_SHNDX

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

0

SHT_SUNW_move

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

0

SHT_SUNW_COMDAT

0

0

SHT_SUNW_syminfo

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

関連付けられている .dynamic セクションのセクションヘッダーインデックス。

SHT_SUNW_verdef

関連付けられている文字列テーブルのセクションヘッダーインデックス。 

セクション内のバージョン定義数。 

SHT_SUNW_verneed

関連付けられている文字列テーブルのセクションヘッダーインデックス。 

セクション内のバージョン依存数。 

SHT_SUNW_versym

関連付けられているシンボルテーブルのセクションヘッダーインデックス。 

0

特殊セクション

さまざまなセクションがプログラム情報と制御情報を保持します。次の表に示すセクションはシステムで使用されますが、これらのセクションには指定された型と属性が存在します。

表 7–10 ELF 特殊セクション

名前 

種類 

属性 

.bss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.comment

SHT_PROGBITS

None

.data.data1

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.dynamic

SHT_DYNAMIC

SHF_ALLOC + SHF_WRITE

.dynstr

SHT_STRTAB

SHF_ALLOC

.dynsym

SHT_DYNSYM

SHF_ALLOC

.eh_frame_hdr

SHT_AMD64_UNWIND

SHF_ALLOC

.eh_frame

SHT_AMD64_UNWIND

SHF_ALLOC + SHF_WRITE

.fini

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.finiarray

SHT_FINI_ARRAY

SHF_ALLOC + SHF_WRITE

.got

SHT_PROGBITS

「大域オフセットテーブル (プロセッサ固有)」を参照してください

.hash

SHT_HASH

SHF_ALLOC

.init

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.initarray

SHT_INIT_ARRAY

SHF_ALLOC + SHF_WRITE

.interp

SHT_PROGBITS

「プログラムインタプリタ」を参照してください

.note

SHT_NOTE

None

.lbss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE

.ldata.ldata1

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE

.lrodata.lrodata1

SHT_PROGBITS

SHF_ALLOC + SHF_AMD64_LARGE

.plt

SHT_PROGBITS

「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください

.preinitarray

SHT_PREINIT_ARRAY

SHF_ALLOC + SHF_WRITE

.rela

SHT_RELA

None

.relname

SHT_REL

「再配置セクション」を参照してください

.relaname

SHT_RELA

「再配置セクション」を参照してください

.rodata.rodata1

SHT_PROGBITS

SHF_ALLOC

.shstrtab

SHT_STRTAB

None

.strtab

SHT_STRTAB

この表のあとの説明を参照してください。 

.symtab

SHT_SYMTAB

「シンボルテーブルセクション」を参照してください

.symtab_shndx

SHT_SYMTAB_SHNDX

「シンボルテーブルセクション」を参照してください

.tbss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE + SHF_TLS

.tdata.tdata1

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE + SHF_TLS

.text

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.SUNW_bss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.SUNW_cap

SHT_SUNW_cap

SHF_ALLOC

.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

.bss

プログラムのメモリーイメージで使用される、初期化されていないデータ。システムは、プログラムが実行を開始すると 0 でデータを初期化することになっています。このセクションは、セクション型 SHT_NOBITS で示しているとおり、ファイル領域を占めません。

.comment

コメント情報 (通常、コンパイルシステムのコンポーネントが使用)。このセクションは、mcs(1) により操作できます。

.data, .data1

プログラムのメモリーイメージで使用される、初期化済みのデータ。

.dynamic

動的リンク情報。詳細は、「動的セクション」を参照してください。

.dynstr

動的リンクに必要な文字列 (もっとも一般的には、シンボルテーブルエントリに関連付けられている名前を表す文字列)。

.dynsym

動的リンクシンボルテーブル。詳細は、「シンボルテーブルセクション」を参照してください。

.eh_frame_hdr.eh_frame

スタックを戻すために使用する呼び出しフレーム情報。

.fini

このセクションを含む実行可能ファイルまたは共有オブジェクトの単一の終了関数で使用される実行可能命令。詳細は、「初期設定および終了ルーチン」を参照してください。

.finiarray

このセクションを含む実行可能ファイルまたは共有オブジェクトの単一の終了配列に使用される関数ポインタの配列。詳細は、「初期設定および終了ルーチン」を参照してください。

.got

大域オフセットテーブル。詳細は、「大域オフセットテーブル (プロセッサ固有)」を参照してください。

.hash

シンボルハッシュテーブル。詳細は、「ハッシュテーブルセクション」を参照してください。

.init

このセクションを含む実行可能ファイルまたは共有オブジェクトの単一の初期化関数で使用される実行可能命令。詳細は、「初期設定および終了ルーチン」を参照してください。

.initarray

このセクションを含む実行可能ファイルまたは共有オブジェクトの単一の初期化配列に使用される関数ポインタの配列。詳細は、「初期設定および終了ルーチン」を参照してください。

.interp

プログラムインタプリタのパス名。詳細は、「プログラムインタプリタ」を参照してください。

.lbss

x64 固有の初期化されていないデータ。このデータは .bss に似ていますが、2G バイトを超えるセクションをサポートする点が異なります。

.ldata.ldata1

x64 固有の初期化済みデータ。このデータは .data に似ていますが、2G バイトを超えるセクションをサポートする点が異なります。

.lrodata.lrodata1

x64 固有の読み取り専用データ。このデータは .rodata に似ていますが、2G バイトを超えるセクションをサポートする点が異なります。

.note

「注釈セクション」に記載された形式の情報。

.plt

プロシージャーのリンクテーブル。詳細は、「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。

.preinitarray

このセクションを含む実行可能ファイルまたは共有オブジェクトの単一の「初期設定前」の配列に使用される関数ポインタの配列。詳細は、「初期設定および終了ルーチン」を参照してください。

.rela

特定のセクションに適用されない再配置情報。このセクションの用途の 1 つは、レジスタの再配置です。詳細は、「レジスタシンボル」を参照してください。

.relname.relaname

再配置情報 (詳細は、「再配置セクション」を参照)。再配置が存在する読み込み可能セグメントがファイルに存在する場合、これらのセクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。慣例により、name は再配置が適用されるセクションの名前になります。したがって、.text の再配置セクションには、通常 .rel.text または .rela.text という名前が存在します。

.rodata, .rodata1

読み取り専用データ (通常はプロセスイメージの書き込み不可セグメントに使用)。詳細は、「プログラムヘッダー」を参照してください。

.shstrtab

セクション名。

.strtab

文字列。通常は、シンボルテーブルエントリに関連付けられた名前を表す文字列です。シンボル文字列テーブルが存在する読み込み可能セグメントがファイルに存在する場合、セクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。

.symtab

シンボルテーブル (詳細は、「シンボルテーブルセクション」を参照)。シンボルテーブルが存在する読み込み可能セグメントがファイルに存在する場合、セクションの属性として SHF_ALLOC ビットがオンになります。そうでない場合、このビットはオフになります。

.symtab_shndx

このセクションには、.symtab による指定に従い、特別なシンボルテーブルセクションインデックス配列が保持されます。関連付けられたシンボルテーブルセクションに SHF_ALLOC ビットが含まれる場合、このセクションの属性も SHF_ALLOC ビットを含みます。そうでない場合、このビットはオフになります。

.tbss

このセクションには、プログラムのメモリーイメージで使用される、初期化されていないスレッド固有データが格納されます。データが新しい実行フロー用に具体化されると、システムはデータを 0 で初期化します。このセクションは、セクション型 SHT_NOBITS で示しているとおり、ファイル領域を占めません。詳細は、第 8 章スレッド固有領域 (TLS)を参照してください。

.tdata.tdata1

これらのセクションは、プログラムのメモリーイメージで使用される、初期化されたスレッド固有データを保持します。その内容のコピーは、それぞれ新しい実行フロー用にシステムによって具体化されます。詳細は、第 8 章スレッド固有領域 (TLS)を参照してください。

.text

プログラムの「テキスト」すなわち実行可能命令。

.SUNW_bss

プログラムのメモリーイメージで使用される、共有オブジェクト用の部分的に初期化されたデータ。データは実行時に初期化されます。このセクションは、セクション型 SHT_NOBITS で示しているとおり、ファイル領域を占めません。

.SUNW_cap

ハードウェアとソフトウェア機能の要件。詳細は、「ハードウェアおよびソフトウェア機能に関するセクション」を参照してください。

.SUNW_heap

dldump(3C) により作成される動的実行可能ファイルのヒープ。

.SUNW_move

部分的に初期化されたデータに関する追加情報。詳細は、「移動セクション」を参照してください。

.SUNW_reloc

再配置情報 (詳細は、「再配置セクション」を参照)。このセクションは再配置セクションが連結されたものであり、個々の再配置レコードに対するより良い参照のローカル性 (局所性) を与えます。再配置レコードのオフセットのみが意味があり、したがってセクション sh_info の値は 0 です。

.SUNW_syminfo

シンボルテーブルの追加情報。詳細は、「Syminfo テーブルセクション」を参照してください。

.SUNW_version

バージョン情報。詳細は、「バージョン管理セクション」を参照してください。

ドット(.) 接頭辞付きのセクション名は、システムで予約されています。これらのセクションの既存の意味が満足できるものであれば、アプリケーションはこれらのセクションを使用できます。アプリケーションは、ドット (.) 接頭辞なしの名前を使用して、システムで予約されたセクションとの競合を回避することができます。オブジェクトファイル形式では、予約されていないセクションを定義できます。オブジェクトファイルには、同じ名前を持つ複数のセクションが存在できます。

プロセッサアーキテクチャー用に予約されるセクション名は、アーキテクチャー名の省略形をセクション名の前に入れることで作成されます。セクション名の前に、e_machine に対して使用されるアーキテクチャー名を入れる必要があります。たとえば、.Foo.psect は、FOO アーキテクチャーで定義される psect セクションです。

既存の拡張セクションは、従来から使用されている名前をそのまま使用しています。

「COMDAT」セクション

「COMDAT」セクションは、セクション名 (sh_name) で一意に識別されます。リンカーが、同じセクション名の SHT_SUNW_COMDAT 型の複数のセクションを検出すると、最初のセクションが保持され、残りのセクションは破棄されます。破棄された SHT_SUNW_COMDAT セクションに適用された再配置はすべて無視されます。破棄されたセクションで定義されたシンボルもすべて削除されます。

さらに、リンカーは、コンパイラ起動時に -xF オプションが指定された場合のセクション再順序付けで使用されるセクション命名規則をサポートします。関数が .sectname%funcname という名前の SHT_SUNW_COMDAT セクションに配置された場合、保持されている最終的な SHT_SUNW_COMDAT セクションは、.sectname という名前のセクションに結合されます。この方法を使用すると、SHT_SUNW_COMDAT セクションは最終的に .text.data、またはほかのセクションに入れられます。

グループセクション

セクションの中には、相互関連のあるグループがあるものがあります。たとえば、インライン関数の out-of-line 定義では、実行可能命令を含むセクション以外にも、別の情報が必要になる場合もあります。この別の情報は、参照される文字定数を含む読み取り専用のデータセクション、1 つまたは複数のデバッギング情報セクション、およびその他の情報セクションなどです。

グループセクション間では内部参照がある場合もあります。ただし、別のオブジェクトからの重複によって、これらのセクションの 1 つが削除 (あるいは、置換) されると、このような参照は意味を成さなくなります。したがって、このようなグループをリンクされたオブジェクトに組み込んだり、オブジェクトから削除したりするときは、1 つの単位として扱います。

タイプ SHT_GROUP のセクションは、そのようなセクションのグループ化を定義します。含んでいるオブジェクトのシンボルテーブルのうちの 1 つからのシンボル名が、そのセクショングループについてのシグニチャを提供します。SHT_GROUP セクションのセクションヘッダーが、識別シンボルエントリを指定します。sh_link メンバーはそのエントリを含むシンボルテーブルセクションのセクションヘッダーインデックスを含み、sh_info メンバーはその識別エントリのシンボルテーブルインデックスを含みます。そのセクションヘッダーの sh_flags メンバーは、値 0 を含みます。そのセクションの名前 (sh_name) は指定されません。

SHT_GROUP セクションのセクションデータは、Elf32_Word エントリの配列です。最初のエントリは、フラグです。残りのエントリは、セクションヘッダーのインデックスのシーケンスです。

現在、次のフラグが定義されています。

表 7–11 ELF グループセクションのフラグ

名前 

値 

GRP_COMDAT

0x1

GRP_COMDAT

GRP_COMDATCOMDAT グループであることを示します。このグループは、同じグループシグニチャを持つものとして重複が定義されているほかのオブジェクトファイル内のほかの COMDAT グループと重複する可能性があります。その場合には、重複グループのうち 1 つのみがリンカーによって保持されます。残りのグループのメンバーは破棄されます。

SHT_GROUP セクション内のセクションヘッダーインデックスは、そのグループを構成するセクションを識別します。これらの各セクションは、SHF_GROUP フラグを sh_flags セクションヘッダーメンバー内に設定していなければなりません。リンカーがそのセクショングループを削除することを決めた場合、リンカーはそのグループのすべてのメンバーを削除します。

未決定の参照を残すことなく、シンボルテーブルの処理を最小限にしてグループの削除を行うには、次の規則に従う必要があります。

ハードウェアおよびソフトウェア機能に関するセクション

SHT_SUNW_cap セクションは、オブジェクトのハードウェアとソフトウェア機能を特定します。このセクションには、次の構造の配列が含まれます。sys/link.h を参照してください。

typedef struct {
        Elf32_Word      c_tag;
        union {
                Elf32_Word      c_val;
                Elf32_Addr      c_ptr;
        } c_un;
} Elf32_Cap;

typedef struct {
        Elf64_Xword     c_tag;
        union {
                Elf64_Xword     c_val;
                Elf64_Addr      c_ptr;
        } c_un;
} Elf64_Cap;

この種の各オブジェクトに対して、c_tagc_un の解釈を制御します。

c_val

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

c_ptr

このオブジェクトは、プログラムの仮想アドレスを表します。

次の機能タグがあります。

表 7–12 ELF 機能配列タグ

名前 

値 

c_un

CA_SUNW_NULL

0

無視される 

CA_SUNW_HW_1

1

c_val

CA_SUNW_SF_1

2

c_val

CA_SUNW_NULL

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

CA_SUNW_HW_1

ハードウェア機能の値を示します。c_val 要素は、関連ハードウェア機能を表す値を含みます。SPARC プラットフォームでは、ハードウェア機能は sys/auxv_SPARC.h に定義されます。x86 プラットフォームでは、ハードウェア機能は sys/auxv_386.h に定義されます。

CA_SUNW_SF_1

ソフトウェア機能の値を示します。c_val 要素は、sys/elf.h に定義される関連ソフトウェア機能を表す値を含みます。

再配置可能オブジェクトには、機能セクションを含めることができます。リンカーは、複数の入力再配置可能オブジェクトからの機能セクションを 1 つの機能セクションに統合します。リンカーを使用すると、オブジェクトの構築時に機能を定義することもできます。「ハードウェアとソフトウェア機能の特定」を参照してください。

ハードウェア機能情報が格納された機能セクションを含む動的オブジェクトでは、そのセクションに関連付けられた PT_SUNWCAP プログラムヘッダーが存在しています。このプログラムヘッダーにより、実行時リンカーは、プロセスで利用可能なハードウェア機能に対してオブジェクトを確認できます。

異なるハードウェア機能を利用する動的オブジェクトは、フィルタを使用して柔軟な実行時環境を提供できます。「ハードウェア機能固有の共有オブジェクト」を参照してください。

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

ハッシュテーブルは、シンボルテーブルへのアクセスを提供する Elf32_Word または Elf64_Word オブジェクトから構成されます。SHT_HASH セクションは、このハッシュテーブルを提供します。ハッシュが関連付けられているシンボルテーブルは、ハッシュテーブルのセクションヘッダーの sh_link エントリに指定されます。ハッシュテーブルの構造についての説明をわかりやすくするために次の図ではラベルを表示しますが、ラベルは仕様の一部ではありません。

図 7–4 シンボルハッシュテーブル

ELF ハッシュテーブル情報の例。

bucket 配列には nbucket 個のエントリが存在し、chain 配列には nchain 個のエントリが存在します。インデックスは 0 から始まります。bucketchain には、シンボルテーブルインデックスを保持します。連鎖テーブルエントリは、シンボルテーブルに対応しています。シンボルテーブルエントリ数は、nchain に等しくなければなりません。したがって、シンボルテーブルインデックスにより、連鎖テーブルエントリも選択されます。

ハッシュ関数はシンボル名を受け取り、bucket インデックスの計算に使用できる値を返します。つまり、ハッシュ関数がある名前に対して値 x を返した場合、bucket [ x% nbucket ] はインデックス y を返します。このインデックスは、シンボルテーブルと連鎖テーブルの両方へのインデックスです。シンボルテーブルエントリが目的の名前でなかった場合、chain[y] は、同じハッシュ値が存在する次のシンボルテーブルエントリを返します。

目的の名前を持つシンボルテーブルエントリが選択されるか、chain エントリの値が STN_UNDEF になるまで、chain リンクをたどることができます。

ハッシュ関数を次に示します。

unsigned long
elf_Hash(const unsigned char *name)
{
    unsigned long h = 0, g;
 
	    while (*name)
	    {
		     h = (h << 4) + *name++;
		     if (g = h & 0xf0000000)
			      h ^= g >> 24;
				   h &= ~g;
	    }
	    return h;
}

移動セクション

一般に、ELF ファイル内では、初期設定されたデータ変数はオブジェクトファイル内で維持されます。データ変数が非常に大きく、初期設定された (ゼロ以外の) 要素が少数の場合でも、変数全体はやはりオブジェクトファイルで維持されます。

FORTRAN COMMON ブロックなど、部分的に初期化された大規模なデータ変数を含むオブジェクトは、多大なディスクスペースオーバーヘッドを引き起こす可能性があります。SHT_SUNW_move セクションは、これらのデータ変数を圧縮するメカニズムを提供します。これにより、関連するオブジェクトのディスクサイズを減らすことができます。

SHT_SUNW_move セクションは、ELF32_Move または Elf64_Move 型の複数のエントリを含みます。これらのエントリは、データ変数を一時的項目 (.bss) として定義することが可能です。これらの項目はオブジェクトファイル内のスペースは使用しませんが、実行時にはオブジェクトのメモリーイメージに反映されます。移動レコードは、完全なデータ変数を構成するためにデータについてメモリーイメージがどのように初期設定されるかを確立します。

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))

これらの構造の要素は次のとおりです。

m_value

初期設定値で、この値はメモリーイメージへ移されます。

m_info

初期設定が適用されるものに関連するシンボルテーブルインデックス、および初期設定されるオフセットのサイズ (単位: バイト)。このメンバーの下位 8 ビットにはサイズを定義します (1、2、4、または 8)。上位ビットにはシンボルインデックスを定義します。

m_poffset

初期設定が適用される関連シンボルからの相対オフセット。

m_repeat

繰り返し回数。

m_stride

スキップの数。この値は、繰り返し初期化を行う際にスキップされる単位数を示します。1 単位は m_info で定義された初期化オブジェクトのサイズです。m_stride が 0 の場合、初期化が連続した単位に対して行われることを示します。

次のデータ定義は、通常、オブジェクトファイル内で 0x8000 バイトを消費します。

typedef struct {
        int     one;
        char    two;
} Data;

Data move[0x1000] = {
        {0, 0},       {1, '1'},     {0, 0},
        {0xf, 'F'},   {0xf, 'F'},   {0, 0},
        {0xe, 'E'},   {0, 0},       {0xe, 'E'}
};

このデータを説明するために、SHT_SUNW_move セクションを使用します。データ項目は、 .bss セクションに定義されます。このデータ項目のゼロ以外の要素は、適切な移動エントリで初期化されます。


$ elfdump -s data | fgrep move
      [17]  0x00020868 0x00008000  OBJT GLOB 0   .bss       move
$ elfdump -m data

Move Section: .SUNW_move
    symndx offset   size repeat stride   value               with respect to
      [17]      8      4      1      1 0x000000000000000001  move
      [17]     12      4      1      1 0x000000000031000000  move
      [17]     24      4      2      1 0x00000000000000000f  move
      [17]     28      4      2      1 0x000000000046000000  move
      [17]     48      4      1      1 0x00000000000000000e  move
      [17]     52      4      1      1 0x000000000045000000  move
      [17]     64      4      1      1 0x00000000000000000e  move
      [17]     68      4      1      1 0x000000000045000000  move

再配置可能オブジェクトから提供される移動セクションは連結され、リンカーにより作成されるオブジェクト内に出力されます。ただし、次の条件が成り立つ場合、リンカーは移動エントリを処理します。この処理は、移動エントリの内容を従来のデータ項目に拡張します。

注釈セクション

ベンダーやシステムエンジニアは、オブジェクトファイルに特別な情報を付加し、ほかのプログラムからその準拠性や互換性を確認できるようにする必要があることがあります。SHT_NOTE 型のセクションと PT_NOTE 型のプログラムヘッダー要素は、この目的に対して使用できます。

次の図に示すように、セクションとプログラムヘッダー要素内の注釈情報は、任意の数のエントリを保持します。64 ビットオブジェクトおよび 32 ビットオブジェクトについては、各エントリはターゲットプロセッサの形式になっている 4 バイトワードの配列です。注釈情報の構造についての説明をわかりやすくするためにラベルを図 7–6 に示しますが、ラベルは仕様の一部ではありません。

図 7–5 注釈の情報

ELF セクションの注釈情報。

nameszname

名前の先頭 namesz バイトには、エントリの所有者または作者を示す、ヌル文字で終わっている文字列が存在します。名前の競合を回避するための正式なメカニズムは存在しません。慣例では、ベンダーは識別子として自身の名前 (“XYZ Computer Company” など) を使用します。name がない場合、namesz の値は 0 になります。name の領域は、パッドを使用して、4 バイトに整列します。必要であれば namesz は、パッドの長さを含みません。

descszdesc

desc の先頭 descsz バイトは、注釈記述を保持します。記述子がない場合、descsz の値は 0 になります。desc の領域は、必要であればパッドを使用して、4 バイトに整列します。descsz はパットの長さを含みません。

type

注釈の解釈を示します。各エントリの作者は、自分で種類を管理します。1 つの type 値に関して複数の解釈が存在する場合があります。したがって、注釈の記述を認識するには、name と type の両方を認識しなければなりません。type は現在、負でない値でなければなりません。

次の図に示す注釈セグメントは、2 つのエントリを保持しています。

図 7–6 注釈セグメントの例

ELF セクションの注釈の例。


注 –

システムは、名前なし (namesz == 0) の注釈情報と、長さ 0 の名前 (name[0] == '\0') を持つ注釈情報を予約していますが、現時点ではタイプは定義していません。ほかのすべての名前には、少なくとも 1 つのヌル以外の文字が存在しなければなりません。


再配置セクション

再配置は、シンボル参照をシンボル定義に関連付ける処理です。たとえば、プログラムが関数を呼び出すとき、関連付けられている呼び出し命令は、実行時に適切な宛先アドレスに制御を渡さなければなりません。再配置可能ファイルには、セクション内容の変更方法を示す情報が存在しなければなりません。この情報により、実行可能オブジェクトファイルと共有オブジェクトファイルは、プロセスのプログラムイメージに関する正しい情報を保持できます。再配置エントリは、これらのデータを保持します。

再配置エントリは、次の構造体を持つことができます。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;
} Elf64_Rela;
r_offset

このメンバーは、再配置処理を適用する位置を与えます。オブジェクトファイルが異なると、このメンバーの解釈が多少異なります。

再配置可能ファイルの場合、値はセクションのオフセットを示します。再配置セクション自身はファイルの別セクションの変更方法を示します。再配置オフセットは、2 番目のセクション内の領域を指定します。

実行可能ファイルまたは共有オブジェクトの場合、値は再配置の影響を受ける領域の仮想アドレスを示します。この情報により、再配置エントリは、実行時リンカーにとって、より意味のあるものになります。

関連するプログラムによるアクセスの効率を高めるため、メンバーの解釈はオブジェクトファイルによって異なりますが、再配置タイプの意味は同じになります。

r_info

このメンバーは、再配置が行われなければならないシンボルテーブルインデックスと、適用される再配置の種類を与えます。たとえば、呼び出し命令の再配置エントリは、呼び出される関数のシンボルテーブルインデックスを保持します。インデックスが STN_UNDEF (未定義シンボルインデックス) の場合、再配置はシンボル値として 0 を使用します。

再配置の種類はプロセッサに固有です。再配置エントリの再配置の種類またはシンボルテーブルインデックスは、それぞれ ELF32_R_TYPE または ELF32_R_SYM をエントリの r_info メンバーに適用した結果です。

#define ELF32_R_SYM(info)             ((info)>>8)
#define ELF32_R_TYPE(info)            ((unsigned char)(info))
#define ELF32_R_INFO(sym, type)       (((sym)<<8)+(unsigned char)(type))

#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))

64 ビット SPARC 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))
r_addend

このメンバーは、再配置可能フィールドに格納される値の計算に使用される定数加数を指定します。

Rela エントリには、明示的加数が含まれます。Rel エントリには、変更される位置に暗黙の加数が存在します。32 ビット SPARC では、Elf32_Rela 再配置エントリのみを使用します。64 ビット SPARC および 64 ビット x86 では、 Elf64_Rela 再配置エントリのみを使用します。したがって、r_addend メンバーは再配置加数として機能します。x86 は、Elf32_Rel 再配置エントリのみを使用します。再配置対象のフィールドは、加数を保持します。すべての場合において、加数と計算された結果は同じバイト順序を使用します。

再配置セクションは、ほかに 2 つのセクションを参照することがあります。 1 つは sh_info セクションヘッダーエントリにより示されるシンボルテーブルで、もう 1 つは sh_link セクションヘッダーエントリにより示される変更対象のセクションです。「セクション」 に、各セクションの関係を示します。再配置オブジェクトに再配置セクションが存在するが、実行可能ファイルや共有オブジェクトが任意の場合は、sh_info エントリが必要です。再配置オフセットが存在すれば、再配置を実行できます。

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

再配置エントリには、次の図に示す命令およびデータフィールドの変更方法が記述されます。ビット番号は、下隅に示されています。

SPARC プラットフォームの場合、再配置エントリはバイト (byte8)、ハーフワード (half16) またはワードに適用されます。

32 ビットの再配置エントリ。

64 ビット SPARC と x64 では、再配置は拡張ワード (xword64) にも適用されます。

64 ビットの再配置エントリ。

x86 の場合、再配置エントリはワード (word32) に適用されます。

x86 再配置エントリ

word32 は、任意バイト整列が存在する 4 バイトを占める 32 ビットフィールドを指定します。これらの値は、x86 アーキテクチャーにおけるほかのワード値と同じバイト順序を使用します。

x86 再配置エントリ

いずれの場合でも r_offset 値は、影響が与えられる領域の先頭バイトのオフセットまたは仮想アドレスを指定します。再配置タイプは、変更されるビットと、これらのビットの値の計算方法を指定します。

次の再配置型の計算では、操作により、再配置可能ファイルが実行可能ファイルまたは共有オブジェクトファイルに変換されることが仮定されています。概念上、リンカーは 1 つまたは複数の再配置可能ファイルを併合して出力します。リンカーは、まず入力ファイルの結合/配置方法を決めます。次に、シンボルの値を更新し、再配置を実行します。実行可能オブジェクトファイルと共有オブジェクトファイルに適用される再配置は類似しており、同じ結果を実現します。このセクションの表では、次の表記が使用されています。

A

再配置可能フィールドの値を計算するために使用される加数。

B

実行時に共有オブジェクトがメモリーに読み込まれるベースアドレス。一般的に、共有オブジェクトファイルは、ベース仮想アドレス 0 で作成されます。ただし、共有オブジェクトの実行アドレスは異なります。「プログラムヘッダー」を参照してください。

G

実行時に再配置エントリのシンボルのアドレスが存在する大域オフセットテーブルへのオフセット。「大域オフセットテーブル (プロセッサ固有)」を参照してください。

GOT

大域オフセットテーブルのアドレス。「大域オフセットテーブル (プロセッサ固有)」を参照してください。

L

シンボルに対するプロシージャーのリンクテーブルエントリのセクションオフセットまたはアドレス。「プロシージャーのリンクテーブル (プロセッサ固有)」を参照してください。

P

再配置される領域のセクションオフセットまたはアドレス (r_offset を使用して計算)。

S

インデックスが再配置エントリ内に存在するシンボルの値。

Z

インデックスが再配置エントリ内に存在するシンボルのサイズ。

SPARC: 再配置型

次の表に示すフィールド名は、再配置型がオーバーフローを検査するかどうかを通知します。計算される再配置値は意図したフィールドより大きい場合があり、再配置型によっては値の適合を検証 (V) したり結果を切り捨てたり (T) することがあります。たとえば、V-simm13 は、計算された値が simm13 フィールドの外部に 0 以外の有意ビットを持つことがないことを意味します。

表 7–13 SPARC: ELF 再配置型

名前 

値 

フィールド 

計算 

R_SPARC_NONE

0

None

None

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

None

この表のあとの説明を参照してください。 

R_SPARC_GLOB_DAT

20

V-word32

S + A

R_SPARC_JMP_SLOT

21

None

この表のあとの説明を参照してください。 

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_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

R_SPARC_5

44

V-imm5

S + A

R_SPARC_6

45

V-imm6

S + 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-word32

S + A

R_SPARC_UA16

55

V-half16

S + A

R_SPARC_GOTDATA_HIX22

80

T-imm22

((S + A - GOT) >> 10) ^ ((S + A - GOT) >> 31)

R_SPARC_GOTDATA_LOX10

81

T-imm13

((S + A - GOT) & 0x3ff) | (((S + A - GOT) >> 31) & 0x1c00)

R_SPARC_GOTDATA_OP_HIX22

82

T-imm22

(G >> 10) ^ (G >> 31)

R_SPARC_GOTDATA_OP_LOX10

83

T-imm13

(G & 0x3ff) | ((G >> 31) & 0x1c00)

R_SPARC_GOTDATA_OP

84

Word32

この表のあとの説明を参照してください。 


注 –

スレッド固有領域の参照に使用できる再配置はほかにも存在します。これらの再配置については、第 8 章スレッド固有領域 (TLS)で説明しています。


いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。

R_SPARC_GOT10

R_SPARC_LO10 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、 R_SPARC_GOT10 は、大域オフセットテーブルの作成をリンカーに指示します。

R_SPARC_GOT13

R_SPARC_13 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、 R_SPARC_GOT13 は、大域オフセットテーブルの作成をリンカーに指示します。

R_SPARC_GOT22

R_SPARC_22 に似ていますが、シンボルの GOT エントリのアドレスを参照する点が異なります。また、 R_SPARC_GOT22 は、大域オフセットテーブルの作成をリンカーに指示します。

R_SPARC_WPLT30

R_SPARC_WDISP30 に似ていますが、シンボルのプロシージャーリンクテーブルエントリのアドレスを参照する点が異なります。また、R_SPARC_WPLT30 は、プロシージャーのリンクテーブル作成をリンカーに指示します。

R_SPARC_COPY

リンカーは、この再配置型を作成して、動的実行可能ファイルが読み取り専用のテキストセグメントを保持できるようにします。この再配置型のオフセットメンバーは、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。「コピー再配置」を参照してください。

R_SPARC_GLOB_DAT

R_SPARC_32 に似ていますが、再配置は GOT エントリを指定されたシンボルのアドレスに設定する点が異なります。この特殊な再配置型を使うと、シンボルと GOT エントリの対応付けを判定できます。

R_SPARC_JMP_SLOT

リンカーは、動的オブジェクトが遅延結合を提供できるようにするため、この再配置型を作成します。この再配置型のオフセットメンバーは、プロシージャーのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャーのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。

R_SPARC_RELATIVE

リンカーは、動的オブジェクト用にこの再配置型を作成します。この再配置型のオフセットメンバーは、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスに相対アドレスを加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して値 0 を指定する必要があります。

R_SPARC_UA32

R_SPARC_32 に似ていますが、整列されていないワードを参照する点が異なります。再配置されるワードは、任意整列が存在する 4 つの別個のバイトとして処理されなければなりません (アーキテクチャーの要求に従って整列されるワードとしては処理されません)。

R_SPARC_LM22

R_SPARC_HI22 に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。

R_SPARC_PC_LM22

R_SPARC_PC22に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。

R_SPARC_HIX22

64 ビットアドレス空間の最上位 4G バイトに限定される実行可能ファイルに対して R_SPARC_LOX10 とともに使用されます。R_SPARC_HI22 に似ていますが、リンク値の 1 の補数を与えます。

R_SPARC_LOX10

R_SPARC_HIX22 とともに使用されます。R_SPARC_LO10 に似ていますが、必ずリンク値のビット 10 からビット 12 までを設定します。

R_SPARC_L44

再配置型 R_SPARC_H44 および R_SPARC_M44 とともに使用され、44 ビット絶対アドレス指定モデルを生成します。

R_SPARC_REGISTER

レジスタシンボルの初期化に使用されます。この再配置型のオフセットメンバーには、初期化されるレジスタ番号が存在します。このレジスタに対応するレジスタシンボルが必要です。このシンボルの種類は SHN_ABS です。

R_SPARC_GOTDATA_OP_HIX22R_SPARC_GOTDATA_OP_LOX10R_SPARC_GOTDATA_OP

これらの再配置はコード変換に対応したものです。

64 ビット SPARC: 再配置型

再配置計算に使用される次の表記は、64 ビット SPARC 固有のものです。

O

再配置可能フィールドの値を計算するために使用される二次的な加数。この加数は、ELF64_R_TYPE_DATA マクロを適用することにより r_info フィールドから抽出されます。

次の表に示す再配置型は、32 ビット SPARC 用に定義された再配置型を拡張または変 更します。「SPARC: 再配置型」を参照してください。

表 7–14 64 ビット SPARC: ELF 再配置型

名前 

値 

フィールド 

計算 

R_SPARC_HI22

9

V-imm22

(S + A) >> 10

R_SPARC_GLOB_DAT

20

V-xword64

S + A

R_SPARC_RELATIVE

22

V-xword64

B + A

R_SPARC_64

32

V-xword64

S + A

R_SPARC_OLO10

33

V-simm13

((S + A) & 0x3ff) + O

R_SPARC_DISP64

46

V-xword64

S + A - P

R_SPARC_PLT64

47

V-xword64

L + A

R_SPARC_REGISTER

53

V-xword64

S + A

R_SPARC_UA64

54

V-xword64

S + A

R_SPARC_H34

85

V-imm22

(S + A) >> 12

次の再配置型には、単純な計算を超えたセマンティクスが存在します。

R_SPARC_OLO10

R_SPARC_LO10 に似ていますが、符号付き13 ビット即値フィールドを十分に使用するために余分なオフセットが追加される点が異なります。

32 ビット x86: 再配置型

次の表に、32 ビット x86 用に定義された再配置を示します。

表 7–15 32 ビット x86: ELF 再配置型

名前 

値 

フィールド 

計算 

R_386_NONE

0

None

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

None

この表のあとの説明を参照してください。 

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

R_386_16

20

word16

S + A

R_386_PC16

21

word16

S + A - P

R_386_8

22

word8

S + A

R_386_PC8

23

word8

S + A - P


注 –

スレッド固有領域の参照に使用できる再配置はほかにも存在します。これらの再配置については、第 8 章スレッド固有領域 (TLS)で説明しています。


いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。

R_386_GOT32

GOT のベースからシンボルの GOT エントリまでの距離を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。

R_386_PLT32

シンボルのプロシージャーのリンクテーブルエントリのアドレスを計算し、かつプロシージャーのリンクテーブルを作成するようにリンカーに指示します。

R_386_COPY

リンカーは、この再配置型を作成して、動的実行可能ファイルが読み取り専用のテキストセグメントを保持できるようにします。この再配置型のオフセットメンバーは、書き込み可能セグメントの位置を参照します。シンボルテーブルインデックスは、現オブジェクトファイルと共有オブジェクトの両方に存在する必要があるシンボルを指定します。実行時、実行時リンカーは共有オブジェクトのシンボルに関連付けられているデータを、オフセットで指定されている位置にコピーします。「コピー再配置」を参照してください。

R_386_GLOB_DAT

GOT エントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと GOT エントリの対応付けを判定できます。

R_386_JMP_SLOT

リンカーは、動的オブジェクトが遅延結合を提供できるようにするため、この再配置型を作成します。この再配置型のオフセットメンバーは、プロシージャーのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャーのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。

R_386_RELATIVE

リンカーは、動的オブジェクト用にこの再配置型を作成します。この再配置型のオフセットメンバーは、相対アドレスを表す値が存在する、共有オブジェクト内の位置を与えます。実行時リンカーは共有オブジェクトが読み込まれる仮想アドレスに相対アドレスを加算することで、対応する仮想アドレスを計算します。この型に対する再配置エントリは、シンボルテーブルインデックスに対して値 0 を指定する必要があります。

R_386_GOTOFF

シンボルの値と GOT のアドレスの差を計算します。この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。

R_386_GOTPC

R_386_PC32 に似ていますが、計算を行う際に GOT のアドレスを使用する点が異なります。この再配置で参照されるシンボルは、通常 _GLOBAL_OFFSET_TABLE_ です。 この再配置型はまた、大域オフセットテーブルを作成するようにリンカーに指示します。

x64: 再配置型

次の表に、x64 用に定義された再配置を示します。

表 7–16 x64: ELF 再配置型

名前 

値 

フィールド 

計算 

R_AMD64_NONE

0

None

None

R_AMD64_64

1

word64

S + A

R_AMD64_PC32

2

word32

S + A - P

R_AMD64_GOT32

3

word32

G + A

R_AMD64_PLT32

4

word32

L + A - P

R_AMD64_COPY

5

None

この表のあとの説明を参照してください。 

R_AMD64_GLOB_DAT

6

word64

S

R_AMD64_JUMP_SLOT

7

word64

S

R_AMD64_RELATIVE

8

word64

B + A

R_AMD64_GOTPCREL

9

word32

G + GOT + A - P

R_AMD64_32

10

word32

S + A

R_AMD64_32S

11

word32

S + A

R_AMD64_16

12

word16

S + A

R_AMD64_PC16

13

word16

S + A - P

R_AMD64_8

14

word8

S + A

R_AMD64_PC8

15

word8

S + A - P

R_AMD64_PC64

24

word64

S + A - P

R_AMD64_GOTOFF64

25

word64

S + A - GOT

R_AMD64_GOTPC32

26

word32

GOT + A + P


注 –

スレッド固有領域の参照に使用できる再配置はほかにも存在します。これらの再配置については、第 8 章スレッド固有領域 (TLS)で説明しています。


これらの再配置型のほとんどの特別なセマンティクスは、x86 で使用されているものと同じです。いくつかの再配置型には、単純な計算を超えたセマンティクスが存在します。

R_AMD64_GOTPCREL

この再配置のセマンティクスは R_AMD64_GOT32 または等しい R_386_GOTPC 再配置と異なります。x64 アーキテクチャーは、命令ポインタに対して相対的なアドレス指定モードを提供します。したがって、アドレスは 1 つの命令で GOT から読み込むことができます。

R_AMD64_GOTPCREL 再配置の計算は、シンボルのアドレスを指定した GOT 内の位置と再配置を適用する位置の間の差を提供します。

R_AMD64_32

計算値は 32 ビットに切り捨てられます。リンカーは、再配置のために生成された値が元の 64 ビット値にゼロ拡張されていることを確認します。

R_AMD64_32S

計算値は 32 ビットに切り捨てられます。リンカーは、再配置のために生成された値が元の 64 ビット値に符号拡張されていることを確認します。

R_AMD64_8R_AMD64_16R_AMD64_PC16R_AMD64_PC8

これらの再配置は x64 ABI には準拠していませんが、文書化するためにここに追加しておきます。R_AMD64_8 再配置は、計算値を 8 ビットに切り詰めます。R_AMD64_16 再配置は、計算値を 16 ビットに切り詰めます。

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

文字列テーブルセクションは、ヌル文字で終了する一連の文字 (一般に文字列と呼ばれている) を保持します。オブジェクトファイルは、これらの文字列を使用してシンボルとセクション名を表します。文字列をインデックスに使用して、文字列テーブルセクションを参照します。

先頭バイト (インデックス 0) は、ヌル文字を保持します。同様に、文字列テーブルの最後のバイトは、ヌル文字を保持します。したがって、すべての文字列は確実にヌル文字で終了します。したがって、すべての文字列は確実にヌル文字で終了します。インデックスが 0 の文字列は、名前を指定しないかヌル文字の名前を指定します (状況に依存する)。

空の文字列テーブルセクションが許可されており、セクションヘッダーの sh_size メンバーに 0 が入ります。0 以外のインデックスは、空の文字列テーブルに対して無効です。

セクションヘッダーの sh_name メンバーは、セクションヘッダー文字列テーブルセクションへのインデックスを保持します。セクションヘッダー文字列テーブルは、ELF ヘッダーの e_shstrndx メンバーで示されます。次の図は、25 バイトの文字列テーブルと、さまざまなインデックスに関連付けられている文字列を示しています。

図 7–7 ELF 文字列テーブル

ELF 文字列テーブルの例。

次の表に、上の図に示した文字列テーブルの文字列を示しています。

表 7–17 ELF 文字列テーブルインデックス

索引 

文字列 

0

None

1

name

7

Variable

11

able

16

able

24

ヌル文字列

例で示しているとおり、文字列テーブルインデックスはセクションのすべてのバイトを参照できます。文字列は 2 回以上出現可能です。部分文字列に対する参照は存在可能です。単一文字列は複数回参照可能です。参照されない文字列も許可されます。

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

オブジェクトファイルのシンボルテーブルには、プログラムのシンボル定義とシンボル参照の検索と再配置に必要となる情報が格納されます。シンボルテーブルインデックスは、この配列への添字です。インデックス 0 はシンボルテーブルの先頭エントリを指定し、また未定義シンボルインデックスとして機能します。表 7–21 を参照してください。

シンボルテーブルエントリの形式は、次のとおりです。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;
st_name

オブジェクトファイルのシンボル文字列テーブルへのインデックス (シンボル名の文字表現を保持)。値が 0 以外の場合、その値はシンボル名を与える文字列テーブルインデックスを表します。値が 0 の場合、シンボルテーブルエントリに名前は存在しません。

st_value

関連付けられているシンボルの値。この値は、状況に応じて絶対値またはアドレスを表します。「シンボル値」を参照してください。

st_size

多くのシンボルは、関連付けられているサイズを持っています。たとえば、データオブジェクトのサイズは、オブジェクトに存在するバイト数です。このメンバーは、シンボルがサイズを持っていない場合またはサイズが不明な場合、値 0 を保持します。

st_info

シンボルの種類および結び付けられる属性。値と意味のリストを、表 7–18 に示します。次のコードは、値の処理方法を示します。sys/elf.h を参照してください。

#define ELF32_ST_BIND(info)          ((info) >> 4)
#define ELF32_ST_TYPE(info)          ((info) & 0xf)
#define ELF32_ST_INFO(bind, type)    (((bind)<<4)+((type)&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))
st_other

シンボルの可視性。値と意味のリストを、表 7–20 に示します。次のコードは、32 ビットオブジェクトと 64 ビットオブジェクトの両方の値を操作する方法を示しています。その他のビットは 0 に設定され、特に意味はありません。

#define ELF32_ST_VISIBILITY(o)       ((o)&0x3)
#define ELF64_ST_VISIBILITY(o)       ((o)&0x3)
st_shndx

すべてのシンボルテーブルエントリは、何らかのセクションに関して定義されます。このメンバーは、該当するセクションヘッダーテーブルインデックスを保持します。いくつかのセクションインデックスは、特別な意味を示します。表 7–4 を参照してください。

このメンバーに SHN_XINDEX が含まれる場合は、実際のセクションヘッダーインデックスが大きすぎてこのフィールドに入りません。実際の値は、タイプ SHT_SYMTAB_SHNDX の関連するセクション内に存在します。

シンボルのバインディングは、st_info フィールドで決定されますが、これにより、リンクの可視性と動作が決定します。

表 7–18 ELF シンボルのバインディング、(ELF32_ST_BINDELF64_ST_BIND)

名前 

値 

STB_LOCAL

0

STB_GLOBAL

1

STB_WEAK

2

STB_LOOS

10

STB_HIOS

12

STB_LOPROC

13

STB_HIPROC

15

STB_LOCAL

局所シンボル。局所シンボルは、局所シンボルの定義が存在するオブジェクトファイルの外部では見えません。同じ名前の局所シンボルは、互いに干渉することなく複数のファイルに存在できます。

STB_GLOBAL

大域シンボル。大域シンボルは、結合されるすべてのオブジェクトファイルで見ることができます。あるファイルの大域シンボルの定義は、その大域シンボルへの別ファイルの未定義参照を解決します。

STB_WEAK

ウィークシンボル。ウィークシンボルは大域シンボルに似ていますが、ウィークシンボルの定義の優先順位は大域シンボルの定義より低いです。

STB_LOOS - STB_HIOS

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

STB_LOPROC - STB_HIPROC

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

大域シンボルとウィークシンボルは、主に 2 つの点で異なります。


注 –

ウィークシンボルは、主にシステムソフトウェアでの使用を意図したものです。アプリケーションプログラムでの使用は推奨されません。


各シンボルテーブルにおいて、STB_LOCAL 結合を持つすべてのシンボルは、ウィークシンボルと大域シンボルの前に存在します。「セクション」に記述されているとおり、シンボルテーブルセクションの sh_info セクションヘッダーメンバーは、最初のローカルではないシンボルに対するシンボルテーブルインデックスを保持します。

シンボルのタイプは st_info フィールドで指定され、これにより、関連付けられた実体の一般的な分類が決定されます。

表 7–19 ELF シンボルのタイプ (ELF32_ST_TYPEELF64_ST_TYPE)

名前 

値 

STT_NOTYPE

0

STT_OBJECT

1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_COMMON

5

STT_TLS

6

STT_LOOS

10

STT_HIOS

12

STT_LOPROC

13

STT_SPARC_REGISTER

13

STT_HIPROC

15

STT_NOTYPE

シンボルの種類は指定されません。

STT_OBJECT

シンボルは、データオブジェクト (変数や配列など) と関連付けられています。

STT_FUNC

シンボルは、関数またはほかの実行可能コードに関連付けられています。

STT_SECTION

シンボルは、セクションに関連付けられています。この種類のシンボルテーブルエントリは主に再配置を行うために存在しており、通常、STB_LOCAL に結び付けられています。

STT_FILE

慣例により、シンボルの名前はオブジェクトファイルに対応するソースファイルの名前を与えます。ファイルシンボルは STB_LOCAL に結び付けられており、セクションインデックスは SHN_ABS です。このシンボルは、存在する場合、ファイルのほかの STB_LOCAL シンボルの前に存在します。

SHT_SYMTAB のシンボルインデックス 1 は、そのオブジェクトファイルを表す STT_FILE シンボルです。慣例により、このシンボルの後にはファイル STT_SECTION シンボルが続きます。これらのセクションシンボルの後には、ローカルになった大域シンボルが続きます。

STT_COMMON

このシンボルは、初期設定されていない共通ブロックを表します。このシンボルは、STT_OBJECT とまったく同じに扱われます。

STT_TLS

シンボルは、スレッド固有領域の実体を指定します。定義されている場合、実際のアドレスではなく、シンボルに割り当てられたオフセットを提供します。

スレッドローカルストレージの再配置では、タイプが STT_TLS のシンボルしか参照できません。割り当て可能なセクションからタイプが STT_TLS のシンボルを参照するには、特別なスレッドローカルストレージ再配置を使用するしか方法がありません。詳細は、第 8 章スレッド固有領域 (TLS)を参照してください。割り当てができないセクションからタイプが STT_TLS のシンボルを参照する際には、この制限はありません。

STT_LOOS - STT_HIOS

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

STT_LOPROC - STT_HIPROC

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

シンボルの可視性は、その st_other フィールドで決まります。この可視性は、再配置可能オブジェクトで指定できます。シンボルの可視性により、シンボルが実行可能ファイルまたは共有オブジェクトの一部になった後のシンボルへのアクセス方法が定義されます。

表 7–20 ELF シンボルの可視性

名前 

値 

STV_DEFAULT

0

STV_INTERNAL

1

STV_HIDDEN

2

STV_PROTECTED

3

STV_DEFAULT

STV_DEFAULT 属性を持つシンボルの可視性は、シンボルの結合タイプで指定されたものになります。大域シンボルおよびウィークシンボルは、それらの定義するコンポーネント (実行可能ファイルまたは共有オブジェクト) の外から見ることができます。局所シンボルは、「隠されて」います。大域シンボルおよびウィークシンボルは、横取りすることもできます。別のコンポーネントの同じ名前の定義によってこれらのシンボルに割り込むこともできます。

STV_PROTECTED

現在のコンポーネント内で定義されたシンボルは、それがほかのコンポーネント内で参照可能であるが横取り可能ではない場合、保護されています。定義コンポーネント内からシンボルへの参照など、あらゆる参照について、コンポーネント内の定義に解決する必要があります。この解決は、シンボル定義がデフォルト規則によって割り込みを行う別のコンポーネント内に存在する場合も、実行する必要があります。STB_LOCAL 結合を持つシンボルは、STV_PROTECTED 可視性を持ちません。

STV_HIDDEN

現在のコンポーネント内で定義されたシンボルは、その名前がほかのコンポーネントから参照することができない場合、「隠されて」います。そのようなシンボルは、保護される必要があります。この属性は、コンポーネントの外部インタフェースの管理に使用されます。そのようなシンボルによって指定されたオブジェクトは、そのアドレスが外部に渡された場合でも、ほかのコンポーネントから参照可能です。

再配置可能オブジェクトに含まれた「隠された」シンボルは、そのオブジェクトが実行可能ファイルまたは共有オブジェクトに含まれる時には、削除されるか STB_LOCAL 結合に変換されます。

STV_INTERNAL

この可視性の属性は、現在予約されています。

可視性の属性は、リンク編集中、実行可能ファイルまたは共有オブジェクト内のシンボルの解決にはまったく影響をおよぼしません。このような解決は、結合タイプによって制御されます。いったんリンカーがその解決を選択すると、これらの属性は次の 2 つの必要条件を課します。どちらの必要条件も、リンクされるコード内の参照は、属性の利点を利用するために最適化されるという事実に基づくものです。

シンボル値がセクション内の特定位置を参照すると、セクションインデックスメンバー st_shndx は、セクションヘッダーテーブルへのインデックスを保持します。再配置時にセクションが移動すると、シンボル値も変化します。シンボルへの参照はプログラム内の同じ位置を指し示し続けます。いくつかの特別なセクションインデックス値は、ほかのセマンティクスが付けられています。

SHN_ABS

このシンボルは、再配置が行われても変わらない絶対値を持ちます。

SHN_COMMON および SHN_AMD64_LCOMMON

このシンボルは、まだ割り当てられていない共通ブロックを示します。シンボル値は、セクションの sh_addralign メンバーに類似した整列制約を与えます。リンカーは st_value の倍数のアドレスにシンボル記憶領域を割り当てます。シンボルのサイズは、必要なバイト数を示します。

SHN_UNDEF

このセクションテーブルインデックスは、シンボルが未定義であることを示します。リンカーがこのオブジェクトファイルを、示されたシンボルを定義するほかのオブジェクトファイルに結合すると、このシンボルに対するこのファイルの参照は定義に結び付けられます。

前述したとおり、インデックス 0 (STN_UNDEF) のシンボルテーブルエントリは予約されています。このエントリは次の値を保持します。

表 7–21 ELF シンボルテーブルエントリ: インデックス 0

名前 

値 

注意 

st_name

0

名前が存在しない 

st_value

0

値は 0 

st_size

0

サイズが存在しない 

st_info

0

種類はない。ローカル結合 

st_other

0

 

st_shndx

SHN_UNDEF

セクションは存在しない 

シンボル値

異なる複数のオブジェクトファイル型のシンボルテーブルエントリは、st_value メンバーに対してわずかに異なる解釈を持ちます。

シンボルテーブル値は、異なる種類のオブジェクトファイルでも似た意味を持ちますが、適切なプログラムはデータに効率的にアクセスできます。

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

シンボルテーブル内のシンボルは、次の順序で書き込まれます。

Solaris OS には、2 つ の特別なシンボルテーブルがあります。

.symtab (SHT_SYMTAB)

このシンボルテーブルには、関連する ELF ファイルを示すあらゆるシンボルが入っています。このシンボルテーブルは、通常は割り当てることができないため、プロセスのメモリーイメージ内では使用できません。

ELIMINATE キーワードと一緒に mapfile を使用すると、.symtab から大域シンボルを削除できます。mapfile を使用した追加シンボルの定義」を参照してください。リンカーの -z redlocsym オプションを使用して、ローカルシンボルを削除することもできます。

.dynsym (SHT_DYNSYM)

このテーブルには、.symtab テーブルのシンボルのうち、動的リンクをサポートするために必要なシンボルだけが入っています。このシンボルテーブルは、割り当てることができるため、プロセスのメモリーイメージ内で使用できます。

.dynsym テーブルは標準 NULL シンボルで始まり、そのあとに大域シンボルが続きます。STT_FILE シンボルは通常、このシンボルテーブルにはありません。STT_SECTION シンボルは、再配置エントリが必要とする場合に存在する可能性があります。

レジスタシンボル

SPARC アーキテクチャーは、レジスタシンボル (大域レジスタを初期化するシンボル) をサポートします。レジスタシンボルに対するシンボルテーブルエントリには、次の値が入ります。

表 7–22 SPARC: ELF シンボルテーブルエントリ: レジスタシンボル

フィールド 

意味 

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

定義済みの SPARC 用レジスタ値を、次に示します。

表 7–23 SPARC: ELF レジスタ番号

名前 

値 

意味 

STO_SPARC_REGISTER_G2

0x2

%g2

STO_SPARC_REGISTER_G3

0x3

%g3

特定の大域レジスタのエントリが存在しないことは、その特定の大域レジスタがオブジェクトで使用されないことを意味します。

Syminfo テーブルセクション

syminfo セクションには、Elf32_Syminfo 型または Elf64_Syminfo 型の複数のエントリが存在します。.SUNW_syminfo セクションには、関連付けられているシンボルテーブル (sh_link) のエントリごとに 1 つのエントリが存在します。

このセクションがオブジェクトに存在している場合、関連付けられているシンボルテーブルからシンボルインデックスを取り出し、このシンボルインデックスを使ってこのセクションに存在する対応する Elf32_Syminfo エントリまたは Elf64_Syminfo エントリを見つけることで、追加シンボル情報を見つけます。関連付けられているシンボルテーブルと、Syminfo テーブルには、必ず同じ数のエントリが存在します。

インデックス 0 は、Syminfo テーブルの現バージョン (SYMINFO_CURRENT) を格納するために使用されます。シンボルテーブルエントリ 0 は必ず UNDEF シンボルテーブルエントリ用に予約されるので、矛盾は発生しません。

Syminfo エントリの形式は、次のとおりです。sys/link.h を参照してください。

typedef struct {
        Elf32_Half      si_boundto;
        Elf32_Half      si_flags;
} Elf32_Syminfo;

typedef struct {
        Elf64_Half      si_boundto;
        Elf64_Half      si_flags;
} Elf64_Syminfo;
si_boundto

.dynamic セクションのエントリへのインデックスで、sh_info フィールドにより示され、Syminfo フラグを増加させます。たとえば、DT_NEEDED エントリは、Syminfo エントリに関連付けられた動的オブジェクトを示します。次の表に示すエントリは、si_boundto に対して予約されています。

名前 

値 

意味 

SYMINFO_BT_SELF

0xffff

自己に結びつけられるシンボル。 

SYMINFO_BT_PARENT

0xfffe

親に結びつけられるシンボル。親は、この動的オブジェクトの読み込みを発生させる最初のオブジェクトです。 

SYMINFO_BT_NONE

0xfffd

シンボルに特別なシンボル結合は含まれません。 

si_flags

このビットフィールドでは、次の表に示すフラグを設定できます。

名前 

値 

意味 

SYMINFO_FLG_DIRECT

0x01

シンボル参照は、定義を含むオブジェクトへ直接関連付けられます。 

SYMINFO_FLG_COPY

0x04

シンボル定義はコピー再配置の結果です。 

SYMINFO_FLG_LAZYLOAD

0x08

遅延読み込みの必要があるオブジェクトに対するシンボル参照です。 

SYMINFO_FLG_DIRECTBIND

0x10

シンボル参照は定義に直接結合される必要があります。 

SYMINFO_FLG_NOEXTDIRECT

0x20

外部参照はこのシンボル定義に直接結合できません。 

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

リンカーで作成されるオブジェクトには、2 つの型のバージョン情報が存在できます。

これらのセクションを形成する構造体は、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;
vd_version

このメンバーは、構造体のバージョンを示します (次の表を参照)。

名前 

値 

意味 

VER_DEF_NONE

0

無効バージョン。 

VER_DEF_CURRENT

>=1

現在のバージョン。 

値 1 は最初のセクション形式を示し、拡張した場合は、より大きい番号の新しいバージョンが必要です。VER_DEF_CURRENT の値は、現在のバージョン番号を示すために必要に応じて変化します。

vd_flags

このメンバーは、バージョン定義に固有の情報を保持します (次の表を参照)。

名前 

値 

意味 

VER_FLG_BASE

0x1

ファイルのバージョン定義。 

VER_FLG_WEAK

0x2

ウィークバージョン識別子。 

基本バージョン定義は、バージョン定義またはシンボルの自動短縮簡約がファイルに適用されている場合、必ず存在します。基本バージョンは、ファイルの予約されたシンボルに対してデフォルトのバージョンを与えます。ウィークバージョン定義には、関連付けられているシンボルは存在しません。「ウィークバージョン定義の作成」を参照してください。

vd_ndx

バージョンインデックス。各バージョン定義には、SHT_SUNW_versym エントリを適切なバージョン定義に関連付ける一意のインデックスが存在します。

vd_cnt

Elf32_Verdaux 配列の要素数。

vd_hash

バージョン定義名のハッシュ値。この値は、「ハッシュテーブルセクション」に記述されているのと同じハッシング機能により生成されます。

vd_aux

この Elf32_Verdef エントリの先頭からバージョン定義名の Elf32_Verdaux 配列までのバイトオフセット。配列の先頭要素は存在しなければなりません。この要素はこの構造体が定義するバージョン定義文字列を指し示します。追加要素は存在可能です。要素の番号は vd_cnt 値で示されます。これらの要素は、このバージョン定義の依存関係を表します。これらの依存関係の各々は、独自のバージョン定義構造体を持っています。

vd_next

この Elf32_Verdef 構造体の先頭から次の Elf32_Verdef エントリまでのバイトオフセット。

vda_name

ヌル文字で終わる文字列への文字列テーブルオフセットで、バージョン定義名を指定します。

vda_next

この Elf32_Verdaux エントリの先頭から次の Elf32_Verdaux エントリまでのバイトオフセット。

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

バージョン依存セクションは、タイプ 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;
vn_version

このメンバーは、構造体のバージョンを示します (次の表を参照)。

名前 

値 

意味 

VER_NEED_NONE

0

無効バージョン。 

VER_NEED_CURRENT

>=1

現在のバージョン。 

値 1 は最初のセクション形式を示し、拡張した場合は、より大きい番号の新しいバージョンが必要です。VER_NEED_CURRENT の値は、現在のバージョン番号を示すために必要に応じて変化します。

vn_cnt

Elf32_Vernaux 配列の要素数。

vn_file

ヌル文字で終わっている文字列への文字列テーブルオフセットで、バージョン依存性のファイル名を指定します。この名前は、ファイル内に存在する .dynamic 依存性のどれかに一致します。「動的セクション」を参照してください。

vn_aux

この Elf32_Verneed エントリの先頭から、関連付けられているファイル依存性から要求されるバージョン定義の Elf32_Vernaux 配列までのバイトオフセット。少なくとも 1 つのバージョン依存性が存在する必要があります。追加バージョン依存性は存在することができ、また番号は vn_cnt 値で示されます。

vn_next

この Elf32_Verneed エントリの先頭から次の Elf32_Verneed エントリまでのバイトオフセット。

vna_hash

バージョン依存性の名前のハッシュ値。この値は、「ハッシュテーブルセクション」に記述されているのと同じハッシング機能により生成されます。

vna_flags

バージョン依存性に固有の情報 (次の表を参照)。

名前 

値 

意味 

VER_FLG_WEAK

0x2

ウィークバージョン識別子。 

ウィークバージョン依存性は、ウィークバージョン定義への最初の結び付きを示します。

vna_other

現在、使用されていません。

vna_name

ヌル文字で終わる文字列への文字列テーブルオフセット。バージョン依存性の名前を与えます。

vna_next

この Elf32_Vernaux エントリの先頭から次の Elf32_Vernaux エントリまでのバイトオフセット。

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

バージョンシンボルセクションは、タイプ SHT_SUNW_versym によって定義されます。このセクションは、次の構造を持つ要素配列で構成されます。

typedef Elf32_Half      Elf32_Versym;
typedef Elf64_Half      Elf64_Versym;

配列の要素数は、関連付けられているシンボルテーブルに存在するシンボルテーブルエントリ数に等しくなければなりません。この値は、セクションの sh_link 値で決定されます。配列の各要素には 1 つのインデックスが存在し、このインデックスは次の表に示す値をとることができます。

表 7–24 ELF バージョン依存インデックス

名前 

値 

意味 

VER_NDX_LOCAL

0

シンボルにローカル適用範囲が存在します。 

VER_NDX_GLOBAL

1

シンボルに大域適用範囲が存在し、ベースバージョン定義に割り当てられています。 

 

>1

シンボルに大域適用範囲が存在し、ユーザー定義バージョン定義に割り当てられています。 

VER_NDX_GLOBAL よりも大きいインデックス値はどれも、SHT_SUNW_verdef セクション内の特定のエントリの vd_ndx 値に対応します。VER_NDX_GLOBAL より大きいインデックス値が存在しない場合、SHT_SUNW_verdef セクションが存在する必要はありません。

動的リンク

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

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

プログラムヘッダー

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

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 に整列)

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 ファイルページ (ページサイズとファイルシステムブロックサイズに依存) に、純粋ではないテキストやデータが含まれます。


注 –

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


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

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

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

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

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

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 セグメントからパス名を取り出し、そのインタプリタファイルのセグメントから初期プロセスイメージを作成します。インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を提供する必要があります。

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

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

各動的タグの値 (2 つの特別な互換性範囲を除く) で d_un union の解釈を決定します。この規則は、外部ツールによる動的タグの解釈をよりシンプルにします。偶数の値を持つタグは、d_ptr を使用する動的セクションのエントリを示します。奇数の値を持つタグは、d_val を使用する動的セクションのエントリ、または d_ptrd_val のどちらも使用しない動的セクションのエントリを示します。特殊値 DT_ENCODING より小さい値を持つタグ、および DT_HIOSDT_LOPROC 間の範囲に入る値を持つタグは、これらの規則には従いません。

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

表 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_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_FEATURE_1

0x6ffffdfc

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_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_FEATURE_1

このオブジェクト特有の機能を示す値。表 7–36 を参照してください。

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_NORELOC

0x400000

内部使用。 

DF_1_GLOBAUDIT

0x1000000

大域監査を確立します。 

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

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

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

このオブジェクトに、直接結合できないシンボルが含まれることを示します。mapfile を使用した追加シンボルの定義」を参照してください。

DF_1_IGNMULDEF

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

DF_1_NOKSYMS

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

DF_1_NOHDR

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

DF_1_NORELOC

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

DF_1_GLOBAUDIT

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

表 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 オプションを使用してオブジェクトに記録されます。「グループの分離」を参照してください。

表 7–36 ELF 動的機能フラグ DT_FEATURE_1

名前 

値 

意味 

DTF_1_PARINIT

0x1

部分的な初期化機能が必要です。 

DTF_1_CONFEXP

0x2

構成ファイルが必要です。 

DTF_1_PARINIT

オブジェクトが部分的な初期化を必要とすることを示します。「移動セクション」を参照してください。

DTF_1_CONFEXP

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

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

一般に位置独立のコードには絶対仮想アドレスは存在できません。大域オフセットテーブルは、内部で使用するデータ内に絶対アドレスを保持します。このため、位置からの独立性とプログラムのテキストの共有性を低下させることなくアドレスが使用可能になります。プログラムは、位置独立のアドレス指定を使用して 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–37 に例示されてはいますが、これらのエントリの元の内容は指定されていません。テーブル内の各エントリは 3 ワード (12 バイト) を占めており、最後のテーブルエントリの後には nop 命令が続きます。

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

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

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

表 7–38 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–39 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–40 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–41 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 再配置エントリを処理します。