リンカーとライブラリ

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

概要

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

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

オブジェクトファイルは、ELF アクセスライブラリ libelf に含まれる関数で処理できます。libelf の説明については、elf(3ELF) を参照してください。libelf を使用するサンプルソースコードは、SUNWosdem パッケージに含まれており、/usr/demo/ELF ディレクトリの下に置かれています。

ファイル形式

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

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

Graphic

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

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

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

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

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


注 -

図 7-1 では ELF ヘッダの直後にプログラムヘッダーテーブルが示され、セクションヘッダーテーブルがセクションの後に続いていますが、実際のファイルは異なる場合があります。また、セクションとセグメントの順序は特に決まっていません。ELF ヘッダーの位置のみがファイル内で固定されています。


データ表現

ここで記述されているとおり、オブジェクトファイルの形式は、8 ビットバイト、32 ビットアーキテクチャ、および 64 ビットアーキテクチャを持つさまざまなプロセッサをサポートしていますが、オブジェクトファイルの形式は、より大きな (またはより小さな) アーキテクチャに拡張できることを意図しています。

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

表 7-1 32 ビットデータタイプ

名前 

サイズ 

整列 

目的 

Elf32_Addr

4

4

符号なしプログラムアドレス 

Elf32_Half

2

2

符号なし、中程度の整数 

Elf32_Off

4

4

符号なしファイルオフセット 

Elf32_Sword

4

4

符号付き整数 

Elf32_Word

4

4

符号なし整数 

unsigned char

1

1

符号なし、短い整数 

表 7-2 64 ビットデータタイプ

名前 

サイズ 

整列 

目的 

Elf64_Addr

8

8

符号なしプログラムアドレス 

Elf64_Half

2

2

符号なし、中程度の整数 

Elf64_Off

8

8

符号なしファイルオフセット 

Elf64_Sword

4

4

符号付き整数 

Elf64_Word

4

4

符号なし整数 

Elf64_Xword

8

8

符号なし、長い整数 

Elf64_Sxword

8

8

符号付き、長い整数 

unsigned char

1

1

符号なし、短い整数 

オブジェクトファイルの形式で定義されるすべてのデータ構造は、該当クラスの自然なサイズと整列ガイドラインに従います。必要であれば、データ構造に明示的にパッドを入れることで、4 バイトオブジェクトに対して 4 バイト整列を保証したり構造サイズを 4 の倍数に設定したりします。また、データはファイルの先頭から適切に整列されます。したがってたとえば、Elf32_Addr 構成要素が存在する構造はファイル内において 4 バイト境界で整列され、Elf64_Addr 構成要素が存在する構造は 8 バイト境界で整列されます。


注 -

移植性を考慮して、ELF ではビットフィールドを使用していません。


ELF ヘッダー

いくつかのオブジェクトファイル制御構造は大きくなることがありまが、そのサイズは ELF ヘッダーに記録されます。オブジェクトファイルの形式が変わった場合、ELF 形式のファイルにアクセスするプログラムは、大きくなったり小さくなったりした制御構造体を扱うことになります。大きくなった場合は、追加された部分を無視することができるかもしれません。小さくなった場合は、無くなった部分の扱いは状況に依存しますし、形式が変更された時に規定されるでしょう。

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

この構成要素は、オブジェクトファイルの種類を示します。

表 7-3 ELF ファイル識別子

名前 

値 

意味 

ET_NONE

0

ファイルタイプが存在しない 

ET_REL

1

再配置可能ファイル 

ET_EXEC

2

実行可能ファイル 

ET_DYN

3

共有オブジェクトファイル 

ET_CORE

4

コアファイル 

ET_LOPROC

0xff00

プロセッサに固有 

ET_HIPROC

0xffff

プロセッサに固有 

コアファイルの内容は指定されていませんが、ET_CORE タイプはコアファイルを示すために予約されます。ET_LOPROC から ET_HIPROC までの値 (それぞれを含む) は、プロセッサ固有の方法で解釈されます。他の値は予約され、必要に応じて新しいオブジェクトファイルの種類に割り当てられます。

e_machine

この構成要素の値は、個々のファイルが必要とするアーキテクチャを指定します。

表 7-4 ELF 機種

名前 

値 

意味 

EM_NONE

0

マシンが存在しない 

EM_SPARC

2

SPARC  

EM_386

3

Intel 80386  

EM_SPARC32PLUS

18

Sun SPARC 32+ 

EM_SPARCV9

43

SPARC V9 

他の値は予約され、必要に応じて新しい機種に割り当てられます (sys/elf.h を参照)。プロセッサ固有の ELF 名の識別には、機種名が使用されます。たとえば、以下に述べるフラグでは接頭辞 EF_ が使用されます。EM_XYZ マシンの WIDGET というフラグは、EF_XYZ_WIDGET と呼ばれます。

e_version

この構成要素は、オブジェクトファイルのバージョンを示します。

表 7-5 ELF バージョン

名前 

値 

意味 

EV_NONE

0

無効なバージョン 

EV_CURRENT

>=1

現在のバージョン 

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

e_entry

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

e_phoff

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

e_shoff

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

e_flags

この構成要素は、ファイルに対応付けられているプロセッサ固有のフラグを保持します。フラグ名は、EF_machine「_flag」という形式をとります。この構成要素は現在、SPARC と IA に対して 0 です。

表 7-6 SPARC: ELF フラグ

名前 

値 

意味 

EF_SPARCV9_MM

0x3

メモリーモデルのマスク 

EF_SPARCV9_TSO

0x0

Total Store Ordering 

EF_SPARCV9_PSO

0x1

Partial Store Ordering 

EF_SPARCV9_RMO

0x2

Relaxed Memory Ordering 

EF_SPARC_EXT_MASK

0xffff00

ベンダー拡張マスク 

EF_SPARC_SUN_US1

0x000200

Sun UltraSPARCTM 1 拡張

EF_SPARC_HAL_R1

0x000400

HAL R1 拡張 

EF_SPARC_SUN_US3

0x000800

Sun UltraSPARC 3 拡張 

e_ehsize

この構成要素は、ELF ヘッダーのサイズ (単位 : バイト) を保持します。

e_phentsize

この構成要素は、ファイルのプログラムヘッダーテーブルの 1 つのエントリのサイズ (単位 : バイト) を保持します。すべてのエントリは同じサイズです。

e_phnum

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

e_shentsize

この構成要素は、1 つのセクションヘッダーのサイズ (単位 : バイト) を保持します。1 つのセクションヘッダーは、セクションヘッダーテーブルの 1 つのエントリです。すべてのエントリは同じサイズです。

e_shnum

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

e_shstrndx

この構成要素は、セクション名文字列テーブルに対応するエントリのセクションヘッダーテーブルインデックスを保持します。ファイルにセクション名文字列テーブルが存在しない場合、この構成要素は値 SHN_UNDEF を保持します。詳細は、「セクション」「文字列テーブル」を参照してください。

ELF 識別

先に述べたとおり、ELF はオブジェクトファイルの枠組みを提供し、複数のプロセッサ、複数のデータ符号化、複数のクラスのマシンをサポートします。このオブジェクトファイルファミリをサポートできるようファイルの初期バイトは、問い合わせが行われるプロセッサに関係なくかつファイルの残りの内容にも関係なくファイルのセマンティクスを指定します。

ELF ヘッダー (とオブジェクトファイル) の初期バイトは、e_ident 構成要素に一致します。

表 7-7 e_ident[ ] 識別インデックス

名前 

値 

目的 

EI_MAG0

0

ファイルの識別 

EI_MAG1

1

ファイルの識別 

EI_MAG2

2

ファイルの識別 

EI_MAG3

3

ファイルの識別 

EI_CLASS

4

ファイルのクラス 

EI_DATA

5

データの符号化 

EI_VERSION

6

ファイルのバージョン 

EI_OSABI

7

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

EI_ABIVERSION

8

ABI のバージョン

EI_PAD

7

パッドバイトの開始 

EI_NIDENT

16

e_ident[] のサイズ

次のインデックスは、マジックナンバーを保持するバイトをアクセスします。

EI_MAG0 - EI_MAG3

ファイルの先頭 4 バイトは、ファイルを ELF オブジェクトファイルとして識別する「マジックナンバー」を保持します。

表 7-8 マジックナンバー

名前 

値 

位置 

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] は、ファイルのクラスまたは容量を示します。

表 7-9 ファイルクラス

名前 

値 

意味 

ELFCLASSNONE

0

無効なクラス 

ELFCLASS32

1

32 ビットオブジェクト 

ELFCLASS64

2

64 ビットオブジェクト 

ファイル形式は、最大マシンのサイズを最小マシンに押しつけることなしにさまざまなサイズのマシン間で互換性が維持されるように設計されています。ファイルのクラスは、オブジェクトファイルそのもののデータ構造によって使用される基本タイプを定義します。

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

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

EI_DATA

バイト e_ident[EI_DATA] は、オブジェクトファイルのプロセッサ固有のデータの符号化を指定します。現在、以下の符号化が定義されています。

表 7-10 データの符号化

名前 

値 

意味 

ELFDATANONE

0

無効な符号化 

ELFDATA2LSB

1

図 7-2 を参照

ELFDATA2MSB

2

図 7-3 を参照

これらの符号化の詳細を以下に示します。他の値は予約され、必要に応じて新しい符号化に割り当てられます。

EI_VERSION

バイト e_ident[EI_VERSION] は、ELF ヘッダーバージョン番号を指定します。現在この値は、e_version表 7-5 で説明しているように、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 に設定されます。オブジェクトファイルを読み取るプログラムは、これらのバイトを無視するべきです。使用されていないバイト列が使用されるようになった場合、EI_PAD の値は変更されます。

ファイルのデータ符号化方式は、ファイル内の基本オブジェクトを解釈する方法を指定します。クラス ELFCLASS32 のファイルは、1、2、および 4 バイトを占めるオブジェクトを使用します。クラス ELFCLASS64 のファイルは、1、2、4、および 8 バイトを占めるオブジェクトを使用します。定義されている符号化方式の下では、オブジェクトは以下のように表されます。バイト番号は、左上隅に示されています。

ELFDATA2LSB を符号化すると、最下位バイトが最低位アドレスを占める 2 の補数値が指定されます。

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

Graphic

ELFDATA2MSB を符号化すると、最上位バイトが最低位アドレスを占める 2 の補数値が指定されます。

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

Graphic

セクション

オブジェクトファイルのセクションヘッダーテーブルを使用すると、すべてのファイルのセクションを見つけ出すことができます。セクションヘッダーテーブルは、以下に示されているとおり、Elf32_Shdr 構造体または Elf64_Shdr 構造体の配列です。セクションヘッダーテーブルインデックスは、この配列への添字です。ELF ヘッダーの e_shoff 構成要素は、ファイルの先頭からセクションヘッダーテーブルまでのバイトオフセットを与えます。e_shnum は、セクションヘッダーテーブルに存在するエントリ数を与えます。e_shentsize は、各エントリのサイズ (単位: バイト) を与えます。

いくつかのセクションヘッダーテーブルインデックスは予約されます。オブジェクトファイルには、これらの特殊インデックスのセクションは存在しません。

表 7-11 セクションの特殊インデックス

名前 

値 

SHN_UNDEF

0

SHN_LORESERVE

0xff00

SHN_LOPROC

0xff00

SHN_BEFORE

0xff00

SHN_AFTER

0xff01

SHN_HIPROC

0xff1f

SHN_ABS

0xfff1

SHN_COMMON

0xfff2

SHN_HIRESERVE

0xffff

SHN_UNDEF

この値は、未定義の、失われた、関連のない、または無意味なセクション参照を示します。たとえば、セクション番号 SHN_UNDEF に関して「定義された」シンボルは、未定義シンボルです。


注 -

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


SHN_LORESERVE

この値は、予約されているインデックスの範囲の下限を指定します。

SHN_LOPROC - SHN_HIPROC

この範囲の値は、プロセッサ固有の使用方法に予約されます。

SHN_BEFORE, SHN_AFTER

これらの値は、SHF_LINK_ORDER および SHF_ORDERED セクションフラグと共に先頭および末尾セクションに順序付けを行います (表 7-14 を参照)。

SHN_ABS

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

SHN_COMMON

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

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-17 を参照してください。

sh_type

この構成要素は、セクションの内容と意味を分類します。セクションの種類とその説明は、表 7-12 を参照してください。

sh_flags

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

sh_addr

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

sh_offset

この構成要素は、ファイルの先頭からセクションの先頭バイトまでのバイトオフセットを与えます。以下に説明されている SHT_NOBITS 型のセクションは、ファイルのスペースを占めません。sh_offset 構成要素は、ファイル内の概念上の位置を示します。

sh_size

この構成要素は、セクションのサイズ (単位: バイト) を与えます。セクションの型が SHT_NOBITS でない限り、セクションはファイルの sh_size バイトを占めます。タイプが SHT_NOBITS のセクションは、0 以外のサイズをとることがありますが、ファイルのスペースは占めません。

sh_link

この構成要素は、セクションヘッダーテーブルインデックスリンクを保持します。このリンクの解釈は、セクションの型に依存します。値は、表 7-15 を参照してください。

sh_info

この構成要素は、追加的な情報を保持します。追加的な情報の解釈は、セクションの型に依存します。値は、表 7-15 を参照してください。

sh_addralign

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

sh_entsize

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

セクションヘッダーの sh_type 構成要素は、表 7-12 に示すようにこのセクションの意味を指定します。

表 7-12 sh_type が保持するセクションの型

名前 

値 

SHT_NULL

0

SHT_PROGBITS

1

SHT_SYMTAB

2

SHT_STRTAB

3

SHT_RELA

4

SHT_HASH

5

SHT_DYNAMIC

6

SHT_NOTE

7

SHT_NOBITS

8

SHT_REL

9

SHT_SHLIB

10

SHT_DYNSYM

11

SHT_SUNW_move

0x6ffffffa

SHT_SUNW_COMDAT

0x6ffffffb

SHT_SUNW_syminfo

0x6ffffffc

SHT_SUNW_verdef

0x6ffffffd

SHT_SUNW_verneed

0x6ffffffe

SHT_SUNW_versym

0x6fffffff

SHT_LOPROC

0x70000000

SHT_HIPROC

0x7fffffff

SHT_LOUSER

0x80000000

SHT_HIUSER

0xffffffff

SHT_NULL

この値は、該当セクションヘッダーが使用されないものであることを示します。このセクションには、関連付けられているセクションは存在しません。セクションヘッダーの他の構成要素の値は不定です。

SHT_PROGBITS

このセクションは、プログラムで定義された情報を保持します。プログラムの形式と意味は、プログラムが独自に決定します。

SHT_SYMTAB, SHT_DYNSYM

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

SHT_STRTAB, SHT_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_SUNW_COMDAT

このセクションには、部分的に初期化されたシンボルを扱うデータが存在します。詳細は、「Comdat セクション」を参照してください。

SHT_SUNW_move

このセクションには、部分的に初期化されたシンボルを扱うデータが存在します。詳細は、「移動セクション」を参照してください。

SHT_SUNW_syminfo

このセクションには、追加シンボル情報を保持するテーブルが存在します。詳細は、「移動セクション」を参照してください。

SHT_SUNW_verdef

このセクションには、このファイルで定義されているきめの細かいバージョンの定義が存在します。詳細は、「バージョン定義セクション」を参照してください。

SHT_SUNW_verneed

このセクションには、イメージの実行に必要なきめの細かい依存性の記述が存在します。詳細は、「バージョン依存セクション」を参照してください。

SHT_SUNW_versym

このセクションには、シンボルとバージョン定義 (ファイルが与える) の関係を記述するテーブルが存在します。詳細は、「バージョンシンボルセクション」を参照してください。

SHT_LOPROC - SHT_HIPROC

この範囲の値は、プロセッサ固有な使用方法用に予約されます。

SHT_LOUSER

この値は、アプリケーションプログラムに対して予約されるインデックスの範囲の下限を示します。

SHT_HIUSER

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

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

表 7-13 セクションヘッダーのテーブルエントリ: インデックス 0

名前 

値 

注意 

sh_name

0

名前が存在しない 

sh_type

SHT_NULL

使用されない 

sh_flags

0

フラグが存在しない 

sh_addr

0

アドレスが存在しない 

sh_offset

0

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

sh_size

0

サイズが存在しない 

sh_link

SHN_UNDEF

リンク情報が存在しない 

sh_info

0

補助情報が存在しない 

sh_addralign

0

整列が存在しない 

sh_entsize

0

エントリが存在しない 

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

表 7-14 セクションの属性のフラグ

名前 

値 

SHF_WRITE

0x1

SHF_ALLOC

0x2

SHF_EXECINSTR

0x4

SHF_MERGE

0x10

SHF_STRINGS

0x20

SHF_INFO_LINK

0x40

SHF_LINK_ORDER

0x80

SHF_OS_NONCONFORMING

0x100

SHF_GROUP

0x200

SHF_MASKOS

0x0ff00000

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 フラグも設定されいる場合は、データ要素は NUILL で終わる文字列で構成されています。各文字のサイズは、セクションヘッダーの sh_entsize フィールドで指定されます。

SHF_STRINGS

このセクション内のデータ要素が、NUILL で終わる文字列で構成されています。各文字のサイズは、セクションヘッダーの sh_entsize フィールドで指定されます。

SHF_INFO_LINK

このセクションヘッダーの sh_info フィールドは、セクションヘッダーのテーブルインデックスを保持します。

SHF_LINK_ORDER

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

sh_info の特殊値である SHN_BEFORE および SHN_AFTER (表 7-11 を参照) は、順序付けされるセット内の他のすべてのセクションに対して、ソートされたセクションがそれぞれ前に付くまたは後に付くことを示します。入力ファイルのリンク行の順序は、1 つの順序付けセット内の複数のセクションがこれらの特殊値のいずれかを持つ場合のために、予約されています。

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

SHF_OS_NONCONFORMING

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

SHF_GROUP

このセクションは、1 つのセクショングループの (おそらく唯一の) 構成要素です。このセクションは、タイプ SHT_GROUP のセクションに参照されなければなりません。SHF_GROUP フラグは、再配置可能オブジェクト (ET_REL に設定された ELF ヘッダーの e_type 構成要素を持つオブジェクト) に含まれたセクションに対してのみ設定することができます。詳細は、「セクショングループ」 を参照してください。

SHF_MASKOS

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

SHF_ORDERED

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

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

特殊な sh_info 値である SHN_BEFORE または SHN_AFTER (表 7-11 を参照) は、整列対象セクションが順序付け対象となる他のすべてのセクションの前または後に存在することを意味します。順序付けの対象となるセクションの複数にこれらの特殊値の 1 つが存在する場合、入力ファイルが指定された順序は保存されます。

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

SHF_EXCLUDE

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

SHF_MASKPROC

このマスクに存在するすべてのビットは、プロセッサ固有な使用方法に予約されます。

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

表 7-15 sh_linksh_info の解釈

sh_type

sh_link

sh_info

SHT_DYNAMIC

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

0

SHT_HASH

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

0

SHT_REL

SHT_RELA

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

再配置が適用されるセクションのセクションヘッダーインデックス。表 7-17 も参照

SHT_SYMTAB

SHT_DYNSYM

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

最後のローカルシンボルのシンボルテーブルインデックスより 1 大きい (STB_LOCAL に対応する)

SHT_GROUP

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

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

SHT_SUNW_move

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

0

SHT_SUNW_COMDAT

0

0

SHT_SUNW_syminfo

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

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

SHT_SUNW_verdef

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

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

SHT_SUNW_verneed

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

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

SHT_SUNW_versym

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

0

セクショングループ

セクションの中には、相互関連のあるグループがあるものがあります。たとえば、インライン関数の 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-16 セクショングループのフラグ

名前 

値 

GRP_COMDAT

0x1

GRP_COMDAT

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

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

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

特殊セクション

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

表 7-17 特殊セクション

名前 

型 

属性 

.bss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.comment

SHT_PROGBITS

なし 

.data

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.data1

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.dynamic

SHT_DYNAMIC

SHF_ALLOC + SHF_WRITE

.dynstr

SHT_STRTAB

SHF_ALLOC

.dynsym

SHT_DYNSYM

SHF_ALLOC

.fini

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.fini_array

SHT_FINI_ARRAY

SHF_ALLOC + SHF_WRITE

.got

SHT_PROGBITS

「大域オフセットテーブル (プロセッサ固有)」を参照

.hash

SHT_HASH

SHF_ALLOC

.init

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.init_array

SHT_INIT_ARRAY

SHF_ALLOC + SHF_WRITE

.interp

SHT_PROGBITS

「プログラムインタプリタ」を参照

.note

SHT_NOTE

なし 

.plt

SHT_PROGBITS

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

.preinit_array

SHT_PREINIT_ARRAY

SHF_ALLOC + SHF_WRITE

.rela

SHT_RELA

なし 

.relname

SHT_REL

「再配置」を参照

.relaname

SHT_RELA

「再配置」を参照

.rodata

SHT_PROGBITS

SHF_ALLOC

.rodata1

SHT_PROGBITS

SHF_ALLOC

.shstrtab

SHT_STRTAB

なし 

.strtab

SHT_STRTAB

後続の .strtab 記述を参照

.symtab

SHT_SYMTAB

「シンボルテーブル」を参照

.text

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

.SUNW_bss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.SUNW_heap

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.SUNW_move

SHT_SUNW_move

SHF_ALLOC

.SUNW_reloc

SHT_rel

SHT_rela

SHF_ALLOC

.SUNW_syminfo

SHT_SUNW_syminfo

SHF_ALLOC

.SUNW_version

SHT_SUNW_verdef

SHT_SUNW_verneed

SHT_SUNW_versym

SHF_ALLOC

.bss

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

.comment

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

.data.data1

これらのセクションは、プログラムのメモリーイメージに使用される初期化されているデータを保持します。

.dynamic

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

.dynstr

このセクションは、動的リンクに必要な文字列 (最も一般的には、シンボルテーブルエントリに関連付けられている名前を表す文字列) を保持します。

.dynsym

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

.fini

このセクションは、プロセス終了時に使用される実行可能命令を保持します。つまり、プログラムが正常終了すると、システムはこのセクションの命令を実行できるようにします。詳細は、「初期設定および終了ルーチン」を参照してください。

.fini_array

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

.got

このセクションは、大域オフセットテーブルを保持します。詳細は、「大域オフセットテーブル (プロセッサ固有)」を参照してください。

.hash

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

.init

このセクションは、プロセス初期化時に使用される実行可能命令を保持します。つまり、プログラムが実行を開始すると、システムはプログラムエントリポイントを呼び出す前にこのセクションの命令を実行できるようにします。詳細は、「初期設定および終了ルーチン」を参照してください。

.init_array

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

.interp

このセクションは、プログラムインタプリタのパス名を保持します。詳細は、「プログラムインタプリタ」を参照してください。

.note

このセクションは、「注釈セクション」に記述されている形式で情報を保持します。

.plt

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

.preinit_array

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

.rela

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

.relname.relaname

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

.rodata.rodata1

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

.shstrtab

このセクションは、セクション名を保持します。

.strtab

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

.symtab

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

.text

このセクションは、プログラムの「テキスト」すなわち実行可能命令を保持します。

.SUNW_bss

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

.SUNW_heap

このセクションは、dldump(3DL) によって作成される動的実行可能ファイルのデータ領域 (ヒープ) を保持します。

.SUNW_move

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

.SUNW_reloc

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

.SUNW_syminfo

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

.SUNW_version

この名前を持つセクションは、バージョン情報を保持します。詳細は、「バージョン情報」を参照してください。

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

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

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

既存の拡張セクション

.conflict

.liblist

.lit8

.sdata

.debug

.line

.reginfo

.stab

.gptab

.lit4

.sbss

.tdesc

文字列テーブル

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

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

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

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

図 7-4 文字列テーブル

Graphic

表 7-18 は、上に示した文字列テーブルの文字列を示しています。

表 7-18 文字列テーブルインデックス

インデックス 

文字列 

0

なし 

1

name

7

Variable

11

able

16

able

24

空文字列 

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

シンボルテーブル

オブジェクトファイルのシンボルテーブルは、プログラムのシンボル定義または参照の探索と再配置に必要な情報を保持します。シンボルテーブルインデックスは、この配列への添字です。インデックス 0 はシンボルテーブルの先頭エントリを指定し、また未定義シンボルインデックスとして機能します。先頭エントリの内容は、このセクションの後の方で記述します。

表 7-19 シンボルテーブルの先頭エントリ

名前 

値 

STN_UNDEF

0

シンボルテーブルエントリの形式 (sys/elf.h で定義されている) は、次のとおりです。


typedef struct {
        Elf32_Word      st_name;
        Elf32_Addr      st_value;
        Elf32_Word      st_size;
        unsigned char   st_info;
        unsigned char   st_other;
        Elf32_Half      st_shndx;
} Elf32_Sym;

typedef struct {
        Elf64_Word      st_name;
        unsigned char   st_info;
        unsigned char   st_other;
        Elf64_Half      st_shndx;
        Elf64_Addr      st_value;
        Elf64_Xword     st_size;
} Elf64_Sym;
st_name

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


注 -

外部 C シンボルは、C とオブジェクトファイルのシンボルテーブルにおいて同じ名前を持ちます。


st_value

この構成要素は、関連付けられているシンボルの値を与えます。この値は、絶対値やアドレスなど (状況に依存する) を表します。「シンボル値」を参照してください。

st_size

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

st_info

この構成要素は、シンボルの種類と結び付けられる属性を指定します。値と意味のリストを以下に示します。次のコードは、値 (sys/elf.h で定義されている) の処理方法を示します。


#define ELF32_ST_BIND(i)             ((i) >> 4)
#define ELF32_ST_TYPE(i)             ((i) & 0xf)
#define ELF32_ST_INFO(b, t)          (((b)<<4)+((t)&0xf))

#define	ELF64_ST_BIND(info)		        ((info) >> 4)
#define	ELF64_ST_TYPE(info)		        ((info) & 0xf)
#define	ELF64_ST_INFO(bind, type)    (((bind)<<4)+((type)&0xf))
st_other

この構成要素は、現在シンボルの可視性のために使用されています。値とその意味に関しては、後述のとおりです。以下のコードは、32 ビットオブジェクトと 64 ビットオブジェクトについて値を操作する方法を示しています。その他のビットは 0 を含んでおり、特に意味はありません。


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

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

シンボルの結び付けは、リンクの可視性と動作を決定します。

表 7-20 シンボルの結び付け (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 セクションヘッダー構成要素は、最初のローカルではないシンボルに対するシンボルテーブルインデックスを保持します。

シンボルの種類は、関連付けられている実体に関する一般的分類を行います。

表 7-21 シンボルの種類 (ELF32_ST_TYPEELF64_ST_TYPE)

名前 

値 

STT_NOTYPE

0

STT_OBJECT

1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_COMMON

5

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 シンボルと、ローカルシンボルに短縮されている大域シンボルが続きます (詳細は、「シンボル範囲の縮小」と、第 5 章「バージョンアップ」を参照)。

STT_COMMON

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

STT_LOOS - STT_HIOS

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

STT_LOPROC - STT_HIPROC

この範囲の値 (両端の値を含む) は、プロセッサ固有の使用方法に対して予約されています。

共有オブジェクトファイルの関数シンボル (STT_FUNC タイプが存在する) は、特別な意味を持っています。別のオブジェクトファイルが共有オブジェクトの関数を参照すると、リンカーは参照されるシンボルのプロシージャのリンクテーブルエントリを自動的に作成します。STT_FUNC 以外のタイプの共有オブジェクトシンボルは、プロシージャのリンクテーブルから自動的には参照されません。

シンボルの可視性は、(再配置可能オブジェクトの中に指定することもできますが、) シンボルがいったん実行可能ファイルまたは共有オブジェクトの一部になってからどのようにアクセスされるかを定義します。

表 7-22 シンボルの可視性

名前 

値 

STV_DEFAULT

1

STV_INTERNAL

2

STV_HIDDEN

3

STV_PROTECTED

4

STV_DEFAULT

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

STV_PROTECTED

現在のコンポーネン内で定義されたシンボルは、それが他のコンポーネント内で参照可能であるが横取り可能ではない場合、保護されています。つまり、定義するコンポーネント内からのそのようなシンボルへの参照は、たとえデフォルトの規則によって間に入るような別のコンポーネントの定義があったとしても、そのコンポーネントの定義にもとづいて解決されなければなりません。STB_LOCAL 結合を持つシンボルは、STV_PROTECTED 可視性を持ちません。

STV_HIDDEN

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

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

STV_INTERNAL

この可視性の属性は、現在予約されています。将来使用される場合は、そのセマンティクスは少なくとも STV_HIDDEN と同じくらい制約の厳しいものとなります。

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

シンボル値がセクション内の特定位置を参照すると、セクションインデックス構成要素 st_shndx は、セクションヘッダーテーブルへのインデックスを保持します。再配置時にセクションが移動すると、シンボル値も変化し、シンボルへの参照はプログラム内の同じ位置を指し示し続けます。いくつかの特殊セクションのインデックス値は、他の意味付けがされています。

SHN_ABS

シンボルは、絶対値 (再配置が行われても変化しない) を持ちます。

SHN_COMMON

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

SHN_UNDEF

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

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

表 7-23 シンボルテーブルエントリ: インデックス 0

名前 

値 

注意 

st_name

0

名前はない 

st_value

0

値は 0 

st_size

0

サイズはない 

st_info

0

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

st_other

0

 

st_shndx

SHN_UNDEF

セクションは存在しない 

シンボル値

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

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

レジスタシンボル

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

表 7-24 SPARC: シンボルテーブルエントリ: レジスタシンボル

フィールド 

意味 

st_name

シンボル名文字列テーブルへのインデックス。または 0 (スクラッチレジスタ)  

st_value

レジスタ番号。整数レジスタの割り当てについては、ABI マニュアルを参照 

st_size

未使用 (0)  

st_info

結び付きは標準的には STB_GLOBAL。種類は STT_SPARC_REGISTER でなければならない

st_other

未使用 (0)  

st_shndx

SHN_ABS (このオブジェクトがこのレジスタシンボルを初期化する場合)。SHN_UNDEF (それ以外の場合)

表 7-25 SPARC: レジスタ番号

名前 

値 

意味  

STO_SPARC_REGISTER_G2

0x2

%g2

STO_SPARC_REGISTER_G3

0x3

%g3

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

Syminfo テーブル

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

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

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

Syminfo エントリの形式は、以下のとおりです。


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_flags

これはビットフィールドであり、表 7-26 に示すようにフラグを設定できます。

表 7-26 Syminfo フラグ

名前 

値 

意味 

SYMINFO_FLG_DIRECT

0x01

このシンボルは、外部オブジェクトを直接参照した 

SYMINFO_FLG_COPY

0x04

このシンボルは、コピー再配置を行なった結果 

SYMINFO_FLG_LAZYLOAD

0x08

このシンボルは、レイジーロード可能な外部オブジェクトを参照する 

si_boundto

sh_info フィールドで示される .dynamic セクションのエントリへのインデックス。このエントリは、DT_* (DT_NEEDED) エントリ (Syminfo エントリに関連付けられている動的オブジェクトを示す) を示します。表 7-27 に示すエントリは、si_boundto に対して予約されています。

表 7-27 si_boundto 予約値

名前 

値 

意味 

SYMINFO_BT_SELF

0xffff

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

SYMINFO_BT_PARENT

0xfffe

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

再配置

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

再配置エントリは、以下の構造体 (sys/elf.h で定義されている) を持つことができます。


typedef struct {
        Elf32_Addr      r_offset;
        Elf32_Word      r_info;
} Elf32_Rel;

typedef struct {
        Elf32_Addr      r_offset;
        Elf32_Word      r_info;
        Elf32_Sword     r_addend;
} Elf32_Rela;

typedef struct {
        Elf64_Addr      r_offset;
        Elf64_Xword     r_info;
} Elf64_Rel;

typedef struct {
        Elf64_Addr      r_offset;
        Elf64_Xword     r_info;
        Elf64_Sxword    r_addend;
} Elf64_Rela;
r_offset

この構成要素は、再配置処理を適用する位置を与えます。再配置可能ファイルの場合、値はセクションの先頭から再配置の影響を受ける領域までのオフセットです。実行可能ファイルまたは共有オブジェクトの場合、値は再配置の影響を受ける領域の仮想アドレスです。

r_info

この構成要素は、再配置が行われなければならないシンボルテーブルインデックスと、適用される再配置の種類を与えます。たとえば、呼び出し命令の再配置エントリは、呼び出される関数のシンボルテーブルインデックスを保持します。インデックスが STN_UNDEF (未定義シンボルインデックス) の場合、再配置はシンボル値として 0 を使用します。再配置の種類はプロセッサに固有です。再配置の種類の動作は以下に記述します。以下のテキストが再配置エントリの再配置の種類またはシンボルテーブルインデックスを参照すると、それぞれ ELF32_R_TYPE または ELF32_R_SYM をエントリの r_info 構成要素に適用した結果が得られます。


#define ELF32_R_SYM(i)                ((i)>>8)
#define ELF32_R_TYPE(i)               ((unsigned char)(i))
#define ELF32_R_INFO(s, t)            (((s)<<8)+(unsigned char)(t))

#define ELF64_R_SYM(info)             ((info)>>32)
#define ELF64_R_TYPE(info)            ((Elf64_Word)(info))
#define ELF64_R_INFO(sym, type)       (((Elf64_Xword)(sym)<<32)+ ¥ 
                                        (Elf64_Xword)(type)

Elf64_Rel および Elf64_Rela 構造の場合、r_info フィールドはさらに 8 ビットの識別子と 24 ビットの付随的なデータに分割されます。


#define ELF64_R_TYPE_DATA(info)       (((Elf64_Xword)(info)<<32)>>40)
#define ELF64_R_TYPE_ID(info)         (((Elf64_Xword)(info)<<56)>>56)
#define ELF64_R_TYPE_INFO(data, type) (((Elf64_Xword)(data)<<8)+ ¥ 
                                        (Elf64_Xword)(type))
r_addend

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

前述したとおり、Elf*_Rela エントリにのみ明示的加数が存在します。タイプ Elf*_Rel のエントリには、変更される位置に暗黙の加数が存在します。32 ビット SPARC は Elf32_Rela エントリ、64 ビット SPARC は Elf64_Rela エントリ、IA は Elf32_Rel エントリをそれぞれ使用します。

再配置セクションは、他の 2 つのセクション (シンボルテーブルと変更されるセクション) を参照します。セクションヘッダーの sh_infosh_link 構成要素 (「セクション」で記述している) は、これらの関係を指定します。異なる複数のオブジェクトファイルに対する再配置エントリには、r_offset 構成要素に関してわずかに異なる解釈が存在します。

r_offset の解釈は異なる複数のオブジェクトファイルでは変化し、その結果、関連プログラムによる効率的アクセスが可能になっていますが、再配置タイプの意味は変化しません。

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

SPARC の場合、再配置エントリは以下の命令/データフィールドの変更方法を記述します (ビット番号はボックスの下隅に表示される)。

Graphic

IA の場合、再配置エントリは以下の命令/データフィールドの変更方法を記述します (ビット番号はボックスの下隅に表示される)。

Graphic

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

Graphic

64 ビット SPARC には、64 ビットワードフィールドが存在します。

Graphic

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

A

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

B

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

G

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

GOT

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

L

シンボルに対する「プロシージャのリンクテーブル」エントリの位置 (セクションオフセットまたはアドレス) を意味します。プロシージャのリンクテーブルエントリは、関数呼び出しを適切な宛先に変更します。リンカーは初期プロシージャのリンクテーブルを作成し、実行時リンカーは実行時にエントリを変更します。詳細は、「プロシージャのリンクテーブル (プロセッサ固有)」を参照してください。

P

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

S

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

SPARC 再配置エントリは、バイト (byte8)、ハーフワード (half16)、またはワード (その他) に適用されます。IA 再配置エントリはワードに適用されます。どの場合も r_offset 値は、影響が与えられる領域の先頭バイトのオフセットまたは仮想アドレスを指定します。再配置タイプは、変更されるビットと、これらのビットの値の計算方法を指定します。

32 ビット SPARC は明示的加数が存在する Elf32_Rela 再配置エントリのみを使用し、64 ビット SPARC は Elf64_Rela を使用します。したがって、r_addend 構成要素は再配置加数として機能します。IA は Elf32_Rel 再配置エントリのみを使用し、再配置されるフィールドは加数を保持します。すべての場合において、加数と計算された結果は同じバイト順序を使用します。

SPARC: 再配置型

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

表 7-28 SPARC: 再配置型

名前 

値 

フィールド 

計算 

R_SPARC_NONE

0

なし 

なし 

R_SPARC_8

1

V-byte8

S + A

R_SPARC_16

2

V-half16

S + A

R_SPARC_32

3

V-word32

S + A

R_SPARC_DISP8

4

V-byte8

S + A - P

R_SPARC_DISP16

5

V-half16

S + A - P

R_SPARC_DISP32

6

V-disp32

S + A - P

R_SPARC_WDISP30

7

V-disp30

(S + A - P) >> 2

R_SPARC_WDISP22

8

V-disp22

(S + A - P) >> 2

R_SPARC_HI22

9

T-imm22

(S + A) >> 10

R_SPARC_22

10

V-imm22

S + A

R_SPARC_13

11

V-simm13

S + A

R_SPARC_LO10

12

T-simm13

(S + A) & 0x3ff

R_SPARC_GOT10

13

T-simm13

G & 0x3ff

R_SPARC_GOT13

14

V-simm13

G

R_SPARC_GOT22

15

T-simm22

G >> 10

R_SPARC_PC10

16

T-simm13

(S + A - P) & 0x3ff

R_SPARC_PC22

17

V-disp22

(S + A - P) >> 10

R_SPARC_WPLT30

18

V-disp30

(L + A - P) >> 2

R_SPARC_COPY

19

なし 

なし 

R_SPARC_GLOB_DAT

20

V-word32

S + A

R_SPARC_JMP_SLOT

21

なし 

R_SPARC_JMP_SLOT」を参照

R_SPARC_RELATIVE

22

V-word32

B + A

R_SPARC_UA32

23

V-word32

S + A

R_SPARC_PLT32

24

V-word32

L + A

R_SPARC_HIPLT22

25

T-imm22

(L + A) >> 10

R_SPARC_LOPLT10

26

T-simm13

(L + A) & 0x3ff

R_SPARC_PCPLT32

27

V-word32

L + A - P

R_SPARC_PCPLT22

28

V-disp22

(L + A - P) >> 10

R_SPARC_PCPLT10

29

V-simm13

(L + A - P) & 0x3ff

R_SPARC_10

30

V-simm10

S + A

R_SPARC_11

31

V-simm11

S + A

R_SPARC_WDISP16

40

V-d2/disp14

(S + A - P) >> 2

R_SPARC_WDISP19

41

V-disp19

(S + A - P) >> 2

R_SPARC_7

43

V-imm7

S + A

R_SPARC_5

44

V-imm5

S + A

R_SPARC_6

45

V-imm6

S + A

いくつかの再配置型には、単純な計算を超えた意味があります。

R_SPARC_GOT10

この再配置型は R_SPARC_LO10 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_GOT13

この再配置型は R_SPARC_13 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_GOT22

この再配置型は R_SPARC_22 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_WPLT30

この再配置型は R_SPARC_WDISP30 に類似しています。ただし、次の点が異なります。つまり、この再配置型はシンボルのプロシージャのリンクテーブルエントリのアドレスを参照し、かつプロシージャのリンクテーブルを作成するようにリンカーに指示します。

R_SPARC_COPY

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

R_SPARC_GLOB_DAT

この再配置型は R_SPARC_32 に似ています。ただし、次の点が異なります。つまり、この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。

R_SPARC_JMP_SLOT

リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、プロシージャのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。

R_SPARC_RELATIVE

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

R_SPARC_UA32

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

SPARC: 再配置型


注 -

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


表 7-29 SPARC: 再配置型

名前 

値 

フィールド 

計算 

R_SPARC_NONE

0

なし 

なし 

R_SPARC_8

1

V-byte8

S + A

R_SPARC_16

2

V-half16

S + A

R_SPARC_32

3

V-word32

S + A

R_SPARC_DISP8

4

V-byte8

S + A - P

R_SPARC_DISP16

5

V-half16

S + A - P

R_SPARC_DISP32

6

V-disp32

S + A - P

R_SPARC_WDISP30

7

V-disp30

(S + A - P) >> 2

R_SPARC_WDISP22

8

V-disp22

(S + A - P) >> 2

R_SPARC_HI22

9

V-imm22

(S + A) >> 10

R_SPARC_22

10

V-imm22

S + A

R_SPARC_13

11

V-simm13

S + A

R_SPARC_LO10

12

T-simm13

(S + A) & 0x3ff

R_SPARC_GOT10

13

T-simm13

G & 0x3ff

R_SPARC_GOT13

14

V-simm13

G

R_SPARC_GOT22

15

T-simm22

G >> 10

R_SPARC_PC10

16

T-simm13

(S + A - P) & 0x3ff

R_SPARC_PC22

17

V-disp22

(S + A - P) >> 10

R_SPARC_WPLT30

18

V-disp30

(L + A - P) >> 2

R_SPARC_COPY

19

なし 

なし 

R_SPARC_GLOB_DAT

20

V-xword64

S + A

R_SPARC_JMP_SLOT

21

なし 

R_SPARC_JMP_SLOT」を参照

R_SPARC_RELATIVE

22

V-xword64

B + A

R_SPARC_UA32

23

V-word32

S + A

R_SPARC_PLT32

24

V-word32

L + A

R_SPARC_HIPLT22

25

T-imm22

(L + A) >> 10

R_SPARC_LOPLT10

26

T-simm13

(L + A) & 0x3ff

R_SPARC_PCPLT32

27

V-disp32

L + A - P

R_SPARC_PCPLT22

28

V-disp22

(L + A - P) >> 10

R_SPARC_PCPLT10

29

V-simm13

(L + A - P) & 0x3ff

R_SPARC_10

30

V-simm10

S + A

R_SPARC_11

31

V-simm11

S + A

R_SPARC_64

32

V-xword64

S + A

R_SPARC_OLO10

33

V-simm13

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

R_SPARC_HH22

34

V-imm22

(S + A) >> 42

R_SPARC_HM10

35

T-simm13

( (S + A) >> 32) & 0x3ff

R_SPARC_LM22

36

T-imm22

(S + A) >> 10

R_SPARC_PC_HH22

37

V-imm22

(S + A - P) >> 42

R_SPARC_PC_HM10

38

T-simm13

( (S + A - P) >> 32) & 0x3ff

R_SPARC_PC_LM22

39

T-imm22

(S + A - P) >> 10

R_SPARC_WDISP16

40

V-d2/disp14

(S + A - P) >> 2

R_SPARC_WDISP19

41

V-disp19

(S + A - P) >> 2

R_SPARC_7

43

V-imm7

(S + A) & 0x7f

R_SPARC_5

44

V-imm5

(S + A) & 0x1f

R_SPARC_6

45

V-imm6

(S + A) & 0x3f

R_SPARC_DISP64

46

V-xword64

S + A - P

R_SPARC_PLT64

47

V-xword64

L + A

R_SPARC_HIX22

48

V-imm22

( (S + A) ^ 0xffffffffffffffff) >> 10

R_SPARC_LOX10

49

T-simm13

( (S + A) & 0x3ff) | 0x1c00

R_SPARC_H44

50

V-imm22

(S + A) >> 22

R_SPARC_M44

51

T-imm10

( (S + A) >> 12) & 0x3ff

R_SPARC_L44

52

T-imm13

(S + A) & 0xfff

R_SPARC_REGISTER

53

V-xword64

S + A

R_SPARC_UA64

54

V-xword64

S + A

R_SPARC_UA16

55

V-half16

S + A

いくつかの再配置型には、単純な計算を超えた意味が存在します。

R_SPARC_GOT10

この再配置型は R_SPARC_LO10 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_GOT13

この再配置型は R_SPARC_13 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_GOT22

この再配置型は R_SPARC_22 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルの大域オフセットテーブルエントリのアドレスを参照し、かつ大域オフセットテーブルを作成するようにリンカーに指示します。

R_SPARC_WPLT30

この再配置型は R_SPARC_WDISP30 に似ています。ただし、次の点が異なります。つまり、この再配置型はシンボルのプロシージャのリンクテーブルエントリのアドレスを参照し、かつプロシージャのリンクテーブルを作成するようにリンカーに指示します。

R_SPARC_COPY

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

R_SPARC_GLOB_DAT

この再配置型は R_SPARC_64 に似ています。ただし、次の点が異なります。つまり、この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。

R_SPARC_JMP_SLOT

リンカーは、動的リンクを行うためにこの再配置型を作成します。この再配置型のオフセット構成要素は、プロシージャのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。

R_SPARC_RELATIVE

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

R_SPARC_UA32

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

R_SPARC_OLO10

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

R_SPARC_HH22

アセンブラは、"imm22-instruction ... %hh (absolute) ..." という形式の命令を認識すると、この再配置型を使用します。

R_SPARC_HM10

アセンブラは、"simm13-instruction ... %hm (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。

R_SPARC_LM22

アセンブラは、"imm22-instruction ... %lm (absolute) ..." という形式の命令を認識すると、この再配置型を使用します。この再配置型は R_SPARC_HI22 に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。

R_SPARC_PC_HH22

アセンブラは、"imm22-instruction ... %hh (pc-relative) ..." という形式の命令を認識すると、この再配置型を使用します。

R_SPARC_PC_HM10

アセンブラは、"simm13-instruction ... %hm (pc-relative) ..." という形式の命令を認識すると、この再配置型を生成します。

R_SPARC_PC_LM22

アセンブラは、"imm22-instruction ... %lm (pc-relative) ..." という形式の命令を認識すると、この再配置型を使用します。この再配置型は R_SPARC_PC22 に似ていますが、妥当性検査ではなく切り捨てを行う点が異なります。

R_SPARC_7

アセンブラは 7 ビットソフトウェアトラップ番号に対してこの再配置型を使用します。

R_SPARC_HIX22

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

R_SPARC_LOX10

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

R_SPARC_H44

アセンブラは、"imm44-instruction ... %h44 (absolute) .." という形式の命令を認識すると、この再配置型を使用します。

R_SPARC_M44

アセンブラは、"imm44-instruction ... %m44 (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。

R_SPARC_L44

この再配置型は再配置型 R_SPARC_H44 および R_SPARC_M44 と共に使用され、44 ビット絶対アドレス指定モデルを生成します。アセンブラは、"imm44-instruction ... %l44 (absolute) ..." という形式の命令を認識すると、この再配置型を生成します。

R_SPARC_REGISTER

この再配置型は、レジスタシンボルを初期化するために使用されます。この再配置型のオフセット構成要素には、初期化されるレジスタ番号が存在します。SHN_ABS 型のこのレジスタには、対応するレジスタシンボルが存在しなければなりません。

IA: 再配置型

表 7-30 IA: 再配置型

名前 

値 

フィールド 

計算 

R_386_NONE

0

なし 

なし 

R_386_32

1

word32

S + A

R_386_PC32

2

word32

S + A - P

R_386_GOT32

3

word32

G + A

R_386_PLT32

4

word32

L + A - P

R_386_COPY

5

なし 

なし 

R_386_GLOB_DAT

6

word32

S

R_386_JMP_SLOT

7

word32

S

R_386_RELATIVE

8

word32

B + A

R_386_GOTOFF

9

word32

S + A - GOT

R_386_GOTPC

10

word32

GOT + A - P

R_386_32PLT

11

word32

L + A

いくつかの再配置型には、単純な計算を超えた意味が存在します。

R_386_GOT32

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

R_386_PLT32

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

R_386_COPY

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

R_386_GLOB_DAT

この再配置型は大域オフセットテーブルエントリを、指定されたシンボルのアドレスに設定します。この特殊な再配置型を使うと、シンボルと大域オフセットテーブルエントリの対応付けを判定できます。

R_386_JMP_SLOT

リンカーは、動的リンクを行うためにこの再配置型を使用します。この再配置型のオフセット構成要素は、プロシージャのリンクテーブルエントリの位置を与えます。実行時リンカーは、プロシージャのリンクテーブルエントリを変更して指定シンボルアドレスに制御を渡します。

R_386_RELATIVE

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

R_386_GOTOFF

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

R_386_GOTPC

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

Comdat セクション

この種類のセクションは、セクション名 (sh_name) で一意に示されます。リンカーが、同じセクション名の SHT_SUNW_COMDAT 型の複数のセクションと出会うと、最初のセクションが保持され、他のすべてのセクションは捨てられます。また、捨てられた SHT_SUNW_COMDAT セクションに適用されたすべての再配置は無視され、かつ捨てられたセクションで定義されたすべてのシンボルも保持されません。

また、リンカーはセクション命名規約をサポートします。このセクション命名規約は、コンパイラが -xF オプションで呼び出されるとき、セクションの再順序付け (「セグメントの宣言」を参照) で使用されます。つまり、セクションが、.<funcname>%<sectname> という名前のセクションに入れられると、保持された最後の SHT_SUNW_COMDAT セクションが、.<sectname> で示されるセクションに合体します。この方法を使用すると、SHT_SUNW_COMDAT セクションを最終的に .text.data、または他のセクションに入れることができます。

バージョン情報

リンカーで作成されるオブジェクトには、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

この構成要素は、構造体自身のバージョンを示します。

表 7-31 バージョン定義構造のバージョン

名前 

値 

意味 

VER_DEF_NONE

0

無効バージョン 

VER_DEF_CURRENT

>=1

現在のバージョン 

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

vd_flags

この構成要素は、バージョン定義に固有の情報を保持します。

表 7-32 バージョン定義セクションのフラグ

名前 

値 

意味 

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_versym 型で定義されており、以下の構造を持つ要素配列からなります。


typedef Elf32_Half      Elf32_Versym;
typedef Elf64_Half      Elf64_Versym;

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

表 7-33 バージョン依存インデックス

名前 

値 

意味 

VER_NDX_LOCAL

0

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

VER_NDX_GLOBAL

1

シンボルに大域適用範囲 (ベースバージョン定義に割り当てられる) が存在する 

 

>1

シンボルに大域適用範囲 (ユーザー定義バージョン定義に割り当てられる) が存在する 

VER_NDX_GLOBAL より大きいインデックス値は、SHT_SUNW_verdef セクションのエントリの vd_ndx 値に一致しなければなりません。VER_NDX_GLOBAL より大きいインデックス値が存在しない場合、SHT_SUNW_verdef セクションが存在する必要はありません。

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

このセクションは、SHT_SUNW_verneed 型で定義されます。このセクションは、ファイルの動的依存性から要求されるバージョン定義を示すことで、ファイルの動的依存性要求を補足します。依存性にバージョン定義が存在する場合のみ、記録がこのセクションにおいて行われます。このセクションの要素の構造体は、次のとおりです。


typedef struct {
        Elf32_Half      vn_version;
        Elf32_Half      vn_cnt;
        Elf32_Word      vn_file;
        Elf32_Word      vn_aux;
        Elf32_Word      vn_next;
} Elf32_Verneed;

typedef struct {
        Elf32_Word      vna_hash;
        Elf32_Half      vna_flags;
        Elf32_Half      vna_other;
        Elf32_Word      vna_name;
        Elf32_Word      vna_next;
} Elf32_Vernaux;

typedef struct {
        Elf64_Half      vn_version;
        Elf64_Half      vn_cnt;
        Elf64_Word      vn_file;
        Elf64_Word      vn_aux;
        Elf64_Word      vn_next;
} Elf64_Verneed;

typedef struct {
        Elf64_Word      vna_hash;
        Elf64_Half      vna_flags;
        Elf64_Half      vna_other;
        Elf64_Word      vna_name;
        Elf64_Word      vna_next;
} Elf64_Vernaux;
vn_version

この構成要素は、構造体自身のバージョンを示します。

表 7-34 バージョン依存構造体のバージョン

名前 

値 

意味 

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

この構成要素は、バージョン依存性に固有の情報を保持します。

表 7-35 バージョン依存構造のフラグ

名前 

値 

意味 

VER_FLG_WEAK

0x2

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

ウィークバージョン依存性は、ウィークバージョン定義への最初の結び付きを示します。詳細は、「バージョン定義の作成」を参照してください。

vna_other

この構成要素は現在、使用されていません。

vna_name

この構成要素は、空文字で終わっている文字列への文字列テーブルオフセットを保持し、バージョン依存性の名前を与えます。

vna_next

この構成要素は、この Elf32_Vernaux エントリの先頭から次の Elf32_Vernaux エントリまでのバイトオフセットを保持します。

注釈セクション

ソフトウェアを開発して販売する場合、オブジェクトファイルに特別な情報を付加して、他のプログラムから準拠性や互換性などを確認できるようにしたいことがあります。SHT_NOTE 型のセクションと PT_NOTE 型のプログラムヘッダー要素は、この目的に対して使用できます。

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

図 7-5 注釈の情報

Graphic

nameszname

name の先頭 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 注釈セグメントの例

Graphic


注 -

システムは注釈情報 (名前が存在せず (namesz == 0)、名前の長さが 0 (name[0] == '¥0') を予約していますが、現在 type を定義していません。他のすべての名前には、少なくとも 1 つの空ではない文字が存在しなければなりません。


移動セクション

一般に、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 の場合、初期設定を m_repeat ユニット連続して行うことを示します。

次のデータ定義は、オブジェクトファイル内で通常 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
        offset  ndx     size    repeat  stride  value   with respect to
        0x8     0x17    4       1       0       0x1     foo
        0xc     0x17    1       1       0       0x31    foo
        0x18    0x17    4       2       2       0xf     foo
        0x1c    0x17    1       2       8       0x46    foo
        0x28    0x17    4       2       4       0xe     foo
        0x2c    0x17    1       2       16      0x45    foo

動的リンク

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

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

プログラムヘッダー

実行可能オブジェクトファイルまたは共有オブジェクトファイルのプログラムヘッダーテーブルは、構造体の配列です (各構造体は、実行されるプログラムを作成するためにシステムが必要とするセグメントやその他の情報を記述します) 。各オブジェクトファイルセグメントには、「セグメントの内容」に記述されているとおり、1 つまたは複数のセクションが存在します。

プログラムヘッダーは、実行可能オブジェクトファイルと共有オブジェクトファイルに対してのみ意味があります。プログラムヘッダーサイズは、ELF ヘッダーの e_phentsize 構成要素と e_phnum 構成要素で指定されます。詳細は、「ELF ヘッダー」を参照してください。

プログラムヘッダーの構造体 (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-36 を参照してください。

p_offset

この構成要素は、ファイルの先頭から、セグメントの先頭バイトが存在する位置までのオフセットを与えます。

p_vaddr

この構成要素は、セグメントの先頭バイトが存在するメモリーの仮想アドレスを与えます。

p_paddr

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

p_filesz

この構成要素は、セグメントのファイルイメージのバイト数を与えます。この構成要素は 0 の場合もあります。

p_memsz

この構成要素は、セグメントのメモリーイメージのバイト数を与えます。この構成要素は 0 の場合もあります。

p_flags

この構成要素は、セグメントに関係するフラグを与えます。定義されているフラグ値は、表 7-37 のとおりです。

p_align

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

いくつかのエントリはプロセスセグメントを記述しますが、それ以外のエントリは補足情報を与え、プロセスイメージには関与しません。セグメントエントリが現れる順序は、以下に明確に記されている場合を除き任意です。定義されている型の値は、次のとおりです。他の値は、将来における使用に備えて保留されます。

表 7-36 セグメント型 p_type

名前 

値 

PT_NULL

0

PT_LOAD

1

PT_DYNAMIC

2

PT_INTERP

3

PT_NOTE

4

PT_SHLIB

5

PT_PHDR

6

PT_LOSUNW

0x6ffffffa

PT_SUNWBSS

0x6ffffffb

PT_SUNWSTACK

0x6ffffffa

PT_HISUNW

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_LOSUNW - PT_HISUNW

この範囲の値は、Sun 固有のセマンティクスに対して予約されます。

PT_SUNWBSS

この配列要素は、PT_LOAD 要素と同じ属性を持ち、.SUNW_bss セクションを記述するために使用されます。

PT_SUNWSTACK

この配列要素はプロセススタックを記述します。現在のところ、そういった要素は 1 つのみ存在し、p_flags フィールドで定義されているアクセスパーミッションのみが有用です。

PT_LOPROC - PT_HIPROC

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


注 -

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


ベースアドレス

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

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

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

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

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

表 7-37 セグメントフラグビット p_flags

名前 

値 

意味 

PF_X

0x1

実行 

PF_W

0x2

書き込み 

PF_R

0x4

読み取り 

PF_MASKPROC

0xf0000000

指定されていない 

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

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

 

値 

正確なフラグ解釈 

許容されるフラグ解釈 

なし

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-17 を参照してください。特定の実行可能ファイルに存在しているセクションを確認するには、dump(1) を使用してください。

PT_DYNAMIC プログラムヘッダー要素は、「動的セクション」で説明しているとおり、.dynamic セクションを指し示します。さらに、.got セクションと .plt セクションには、位置に依存しないコードと動的リンクに関係する情報が存在します。

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

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

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

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

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

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

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

次に SPARC バージョンの例を示します。

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

Graphic

表 7-39 SPARC: プログラムヘッダーセグメント(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

次に IA バージョンの例を示します。

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

Graphic

表 7-40 IA: プログラムヘッダーセグメント (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 のシステムバイナリを反映したものです (表 8-1 を参照)。


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

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

図 7-9 SPARC: プロセスイメージセグメント

Graphic

図 7-10 IA: プロセスイメージセグメント

Graphic

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

一方、通常は共有オブジェクトのセグメントには、位置に依存しないコードが存在します。(背景については、第 2 章「リンカー」を参照してください。) したがって、セグメントの仮想アドレスは、実行動作を無効にすることなくプロセスによって異なることができます。

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

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

表 7-41 SPARC: 共有オブジェクトのセグメントアドレスの例

ソース 

テキスト 

データ 

ベースアドレス 

ファイル 

0x0

0x4000

0x0

プロセス 1 

0xc0000000

0xc0024000

0xc0000000

プロセス 2 

0xc0010000

0xc0034000

0xc0010000

プロセス 3 

0xd0020000

0xd0024000

0xd0020000

プロセス 4 

0xd0030000

0xd0034000

0xd0030000

表 7-42 IA: 共有オブジェクトセグメントアドレスの例

ソース 

テキスト 

データ 

ベースアドレス 

ファイル 

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 セグメントからパス名を取り出し、インタプリタファイルのセグメントから初期プロセスイメージを作成します。つまり、システムは元の実行可能ファイルのセグメントイメージを使用する代わりに、インタプリタのメモリーイメージを作成します。したがって、インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を与えなければなりません。

インタプリタは、次の 2 つの方法のどちらかで制御を受け取ります。方法 1: インタプリタは、実行可能ファイルを読み込むためのファイル記述子 (先頭に位置付けられている) を受け取ることができます。インタプリタは、このファイル記述子を使用して、実行可能ファイルのセグメントをメモリーに読み込んだり対応付けしたりできます。方法 2: 実行可能ファイルの形式によっては、システムはインタプリタにファイル記述子を与える代わりに実行可能ファイルをメモリーに読み込みます。

ファイル記述子が異なる可能性があることを除き、インタプリタの初期プロセス状態は、実行可能ファイルの初期プロセス状態に一致します。インタプリタ自身が、2 番目のインタプリタを必要とすることは許可されません。インタプリタは、共有オブジェクトファイルまたは実行可能ファイルです。

実行時リンカー

リンカーは、動的リンクを使用する実行可能ファイルを作成するとき、PT_INTERP 型のプログラムヘッダー要素を実行可能ファイルに付加し、実行時リンカーをプログラムインタプリタとして呼び出すようにシステムに指示します。exec(2) と実行時リンカーは、協調してプログラムのプロセスイメージを作成します。この処理には以下の動作が伴います。

リンカーはまた、実行時リンカーが実行可能オブジェクトファイルと共有オブジェクトファイルを処理するときの手助けになるさまざまなデータを作成します。先出のプログラムヘッダーセグメントで示されているとおり、これらのデータは読み込み可能セグメントに存在します。したがって、これらのデータは実行時に使用可能です。(正確なセグメント内容はプロセッサに固有であることを思い出してください。)

「プログラムの読み込み (プロセッサ固有)」で説明しているとおり、共有オブジェクトは、ファイルのプログラムヘッダーテーブルに記録されているアドレスとは異なる仮想メモリーアドレスに置かれることができます。実行時リンカーは、アプリケーションが制御を取得する前に、メモリーイメージを再配置して絶対アドレスを更新します。プログラムヘッダーテーブルに指定されているアドレスにライブラリが読み込まれた場合、絶対アドレス値は正しいのですが、通常、このようなことは起きません。

プロセス環境 (exec(2) を参照) に、空ではない値を持つ LD_BIND_NOW という変数が存在する場合、実行時リンカーは、プログラムに制御を渡す前にすべての再配置を処理します。たとえば、以下の各環境エントリは、この動作を指定します。


LD_BIND_NOW=1
LD_BIND_NOW=on  
LD_BIND_NOW=off

実行時リンカーは、プロシージャのリンクテーブルエントリを遅延評価できます。その場合、呼び出されない関数の解決/再配置に費やされる無駄を回避できます。詳細は、「プロシージャのリンクテーブル (プロセッサ固有)」を参照してください。

動的セクション

オブジェクトファイルが動的リンクに関係している場合、このオブジェクトファイルのプログラムヘッダーテーブルには、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-43 は、実行可能オブジェクトファイルと共有オブジェクトファイルのタグ要求についてまとめています。タグに「必須」という印が付いている場合、動的リンク配列にはその型のエントリが存在しなければなりません。また、「任意」は、タグのエントリが現れてもよいですが必須ではないことを意味します

表 7-43 動的配列タグ d_tag

名前 

値 

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_ENCODINGS

32

未指定 

未指定 

未指定 

DT_PREINIT_ARRAY

32

d_ptr

任意 

任意 

DT_PREINIT_ARRAYSZ

33

d_val

任意 

任意 

DT_LOOS

0x6000000d

未指定 

未指定 

未指定 

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

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_AUXILIARY

0x7ffffffd

d_val

未指定 

任意 

DT_USED

0x7ffffffe

d_val

任意 

任意 

DT_FILTER

0x7fffffff

d_val

未指定 

任意 

DT_LOPROC

0x70000000

未指定 

未指定 

未指定 

DT_SPARC_REGISTER

0x70000001

d_val

任意 

任意 

DT_HIPROC

0x7fffffff

未指定 

未指定 

未指定 

DT_NULL

DT_NULL タグが付けられたエントリは、_DYNAMIC 配列の終わりを示します。

DT_NEEDED

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

DT_PLTRELSZ

この要素は、プロシージャのリンクテーブルに関連付けられている再配置エントリの合計サイズ (単位: バイト) を保持します。DT_JMPREL 型のエントリが存在する場合、DT_PLTRELSZ 型のエントリも必要です。

DT_PLTGOT

この要素は、プロシージャのリンクテーブルまたは大域オフセットテーブルに関連付けられているアドレスを保持します。

DT_HASH

この要素は、シンボルハッシュテーブル (「ハッシュテーブル」に記述されている) を指し示します。ハッシュテーブルは、DT_SYMTAB 要素で示されるシンボルテーブルを参照します。

DT_STRTAB

この要素は、文字列テーブル (この章の前半部分で記述している) のアドレスを保持します。文字列テーブルには、実行時リンカーが必要とするシンボル名、依存性名、および他の文字列が存在します。

DT_SYMTAB

この要素は、再配置テーブル (この章の前半部分で記述している) のアドレスを保持します。32 ビットクラスのファイルに対しては Elf32_Sym エントリ、64 ビットクラスのファイルに対しては ELF 64_sym エントリが存在します。

DT_RELA

この要素は、再配置テーブル (この章の前半部分で記述している) のアドレスを保持します。再配置テーブルのエントリ (32 ビットファイルクラス用の Elf32_Rela、64 ビットファイルクラス用の ELF 64_Rela など) には、明示的加数が存在します。

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

この要素が存在する場合、動的構造体には DT_RELASZ 要素と DT_RELAENT 要素も存在しなければなりません。再配置がファイルに対して「必須」の場合、DT_RELA または DT_REL が使用可能です (これらは両方とも使用可能ですが、必要ではありません)。

DT_RELASZ

この要素は、DT_RELA 再配置テーブルの合計サイズ (単位: バイト) を保持します。

DT_RELAENT

この要素は、DT_RELA 再配置エントリのサイズ (単位: バイト) を保持します。

DT_STRSZ

この要素は、文字列テーブルのサイズ (単位: バイト) を保持します。

DT_SYMENT

この要素は、シンボルテーブルエントリのサイズ (単位: バイト) を保持します。

DT_INIT

この要素は、初期化関数のアドレスを保持します (初期化関数については、「初期設定関数および終了関数」で記述しています)。

DT_FINI

この要素は、終了関数のアドレスを保持します (終了関数については、「初期設定関数および終了関数」に記述されています)。

DT_SONAME

この要素は、空文字で終わっている文字列の文字列テーブルオフセットを保持し、共有オブジェクトの名前を与えます。このオフセットは、DT_STRTAB エントリに記録されているテーブルへのインデックスです。これらの名前については、「共有オブジェクトの依存性」を参照してください。

DT_RPATH

この要素は、ライブラリ検索パス (空文字で終わっている文字列) 文字列テーブルオフセットを保持します (ライブラリ検索パスについては、「依存関係を持つ共有オブジェクト」で記述しています)。このオフセットは、DT_STRTAB エントリに記録されているテーブルへのインデックスです。この使用は、DT_RUNPATH に置き換えられました。

DT_SYMBOLIC

この要素は、オブジェクトが、リンク編集時に適用されたシンボル結合を含むかどうかを示します。-Bsymbolic の使用」も参照してください。この使用は、DF_SYMBOLIC に置き換えられました。

DT_REL

この要素は DT_RELA に似ていますが、テーブルに暗黙の加数 (32 ビットファイルクラス用の Elf32_Rel など) が存在する点が異なります。この要素が存在する場合、動的構造体には DT_RELSZ 要素と DT_RELENT 要素も存在しなければなりません。

DT_RELSZ

この要素は、DT_REL 再配置テーブルの合計サイズ (単位: バイト) を保持します。

DT_RELENT

この要素は、DT_REL 再配置エントリのサイズ (単位: バイト) を保持します。

DT_PLTREL

この要素は、プロシージャのリンクテーブルが参照する再配置エントリの型を指定します。d_val 要素は、必要に応じて DT_REL または DT_RELA を保持します。1 つのプロシージャのリンクテーブルでは、すべての再配置は、同じ再配置を使用しなければなりません。

DT_DEBUG

この要素は、デバッグ時に使用されます。

DT_TEXTREL

この構成要素が存在しない場合、再配置エントリが書き込み不可セグメント (プログラムヘッダーテーブルのセグメントのアクセス権で指定されます) に対する変更を発生させてはならないことを意味します。この構成要素が存在する場合、1 つまたは複数の再配置エントリが書き込み不可セグメントに対する変更を要求する可能性があり、実行時リンカーはそれに応じて対応することができます。この使用は、DF_TEXTREL フラグに置き換えられました。

DT_JMPREL

このエントリが存在する場合、このエントリの d_ptr 要素は、プロシージャのリンクテーブルにのみ関連付けられている再配置エントリのアドレスを保持します。これらの再配置エントリを分離しておくと、遅延結合が有効の場合、実行時リンカーはプロセス初期化時にこれらの再配置エントリを無視します。このエントリが存在する場合、DT_PLTRELSZ 型と DT_PLTREL 型の関連エントリも存在しなければなりません。

DT_POSFLAG_1

このエントリが存在する場合、このエントリの d_val 要素は、さまざまな状態フラグを保持します。これらのフラグは、.dynamic セクション内の直後の DT_* エントリに適用されます。

DT_BIND_NOW

このエントリが共有オブジェクトまたは実行可能ファイル内に存在する場合、このエントリは、プログラムに制御を渡す前に、このエントリを含むオブジェクトについてのすべての再配置を処理するよう実行時リンカーに指示します。環境で指定された、または dlopen(3DL) を介した場合、このエントリの存在は、このオブジェクトについてレイジー結合を使用するようにという指示よりも優先されます。この使用は、DF_BIND_NOW フラグに置き換えられました。

DT_INIT_ARRAY

この要素は、「初期設定関数および終了関数」に記述されている、初期設定関数へのポインタの配列のアドレスを保持します。

DT_FINI_ARRAY

この要素は、「初期設定関数および終了関数」に記述されている、終了関数へのポインタの配列のアドレスを保持します。

DT_RUNPATH

この要素は、「依存関係を持つ共有オブジェクト」に記述されている、NULL で終わる検索ライブラリの検索パス文字列の文字列テーブルオフセットを保持します。このオフセットは、DT_STRTAB エントリに記録されたテーブルに対するインデックスです。

DT_FLAGS

この要素は、読み込まれるオブジェクトに特有のフラグ値を保持します。各フラグ値は、DF_flag_name という名前を持ちます。定義された値とその意味は後述されています。その他のすべての値は予約されています。

DT_ENCODING

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

DT_PREINIT_ARRAY

この要素は、「初期設定関数および終了関数」に記述されている、初期設定前関数へのポインタの配列のアドレスを保持します。DT_PREINIT_ARRAY テーブルは実行可能ファイル内でのみ処理されます。共有オブジェクト内に含まれている場合は無視されます。

DT_PREINIT_ARRAYSZ

この要素は、DT_PREINIT_ARRAY エントリにポイントされた初期設定前関数の配列のサイズ (単位: バイト) を保持します。1 つのオブジェクトが DT_PREINIT_ARRAY エントリを持つ場合は、このオブジェクトは DT_PREINIT_ARRAYSZ エントリも持つ必要があります。DT_PREINIT_ARRAY と同様、このエントリは共有オブジェクト内に現れた場合は無視されます。

DT_LOOS - DT_HIOS

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

DT_SYMINFO

この要素は、SHT_SUNW_syminfo セクションのアドレスを保持します。

DT_SYMINENT

この要素は、SHT_SUNW_syminfo テーブルエントリのサイズ (単位: バイト) を保持します。

DT_SYMINSZ

この要素は、SHT_SUNW_syminfo セクションのサイズ (単位: バイト) を保持します。

DT_VERDEF

この要素は、バージョン定義テーブル (この章の前半部分で記述している) のアドレスを保持します。32 ビットクラスのファイルに対しては Elf32_Verdef エントリ、64 ビットクラスのファイルに対しては Elf64_Verdef エントリが存在します。詳細は、「バージョン定義セクション」を参照してください。これらのエントリ内の要素には、DT_STRTAB エントリに記録されているテーブルへのインデックスが存在します。

DT_VERDEFNUM

この要素は、バージョン定義テーブルのエントリ数を指定します。

DT_VERNEED

この要素は、バージョン依存性テーブル (この章の前半部分で記述している) のアドレスを保持します。32 ビットクラスのファイルに対しては Elf32_Verneed エントリ、64 ビットクラスのファイルに対しては Elf64_Verneed エントリが存在します。詳細は、「バージョン依存セクション」を参照してください。これらのエントリ内の要素には、DT_STRTAB エントリに記録されているテーブルへのインデックスが存在します。

DT_VERNEEDNUM

この要素は、バージョン依存性テーブルのエントリ数を指定します。

DT_RELACOUNT

すべての Elf32_Rela あるいは Elf64_Rela R_*_RELATIVE 再配置は単一のブロックに入っており、このエントリはそのブロックのエントリ数を指定します。これにより、実行時リンカー は RELATIVE 再配置の処理を合理化できます。

DT_RELCOUNT

すべての Elf32_Rel R_*_RELATIVE 再配置は単一のブロックに入っており、このエントリはそのブロックのエントリ数を指定します。これにより、実行時リンカーは RELATIVE 再配置の処理を合理化できます。

DT_AUXILIARY

この要素は、空文字で終わっている文字列 (オブジェクトに命名している) の文字列テーブルオフセットを保持します。このオフセットは、DT_STRTAB エントリに記録されているテーブルへのインデックスです。補助オブジェクト内のシンボルは、このオブジェクト内のシンボルに優先して使用されます。

DT_FILTER

この要素は、オブジェクトを示す文字列 (空文字で終わっている文字列) の文字列テーブルオフセットを保持します。このオフセットは、DT_STRTAB エントリに記録されているテーブルへのインデックスです。このオブジェクトのシンボルテーブルは、命名されたオブジェクトのシンボルテーブルのフィルタとして使用されます。

DT_CHECKSUM

この要素は、オブジェクトの選択されたセクションの簡単なチェックサムを保持します。gelf_checksum(3ELF) を参照してください。

DT_MOVEENT

この要素は、SHT_SUNW_move で定義されるセクションの合計サイズを保持します。「移動セクション」を参照してください。

DT_MOVESZ

この要素は、DT_MOVETAB 移動エントリのサイズ (単位: バイト) を保持します。

DT_MOVETAB

この要素は、移動テーブル (この章の前半部分で記述している) のアドレスを保持します。移動テーブルのエントリには、32 ビットクラスのファイルに対する Elf32_Move エントリ、64 ビットクラスのファイルに対する Elf64_Move エントリが存在します。

DT_CONFIG

この要素は、構成ファイルを定義する文字列 (ヌル文字で終端している文字列) の文字列テーブルオフセットを保持します。このオフセットは DT_STRTAB エントリに記録されているテーブルへのインデックスです。構成ファイルは、検索パス、ディレクトリキャッシュ、または代替オブジェクトを提供し、通常 DT_CONFIG エントリを指定するアプリケーションに固有です。crle(1) およびリンカーの -c オプションを参照してください。

DT_DEPAUDIT

この要素は、1 つあるいは複数の監査ライブラリを定義する文字列 (ヌル文字で終端している文字列) の文字列テーブルオフセットを保持します。このオフセットは DT_STRTAB エントリに記録されているテーブルへのインデックスです。監査ライブラリは実行時に、このオブジェクトを監査するために使用されます。リンカーの-P オプションを参照してください。

DT_AUDIT

この要素は、1 つあるいは複数の監査ライブラリを定義する文字列 (ヌル文字で終端している文字列) の文字列テーブルオフセットを保持します。このオフセットは DT_STRTAB エントリに記録されているテーブルへのインデックスです。監査ライブラリは実行時に、このオブジェクトを監査するために使用されます。リンカーの -p オプションを参照してください。

DT_FLAGS_1

このエントリが存在する場合、このエントリの d_val 要素は、さまざまな状態フラグを保持します。表 7-45 を参照してください。

DT_FEATURE_1

このエントリが存在する場合、このエントリの d_val 構成要素は実行時機能要求を定義する DTF_1_ フラグを保持します。関数 _check_rtld_feature() は、通常、コンパイラ供給の起動コードから実行時に呼び出され、要求された機能が存在することを確認します。「機能チェッカ」、および表 7-47 を参照してください。

DT_VALRNGLO - DT_VALRNGHI

この範囲の値は、動的構造体内の d_un.d_val フィールドで使用されます。

DT_ADDRRNGLO - DT_ADDRRNGHI

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

DT_SPARC_REGISTER

この要素には、STT_SPARC_REGISTER シンボルのインデックスが存在します。シンボルテーブルの各 STT_SPARC_REGISTER シンボルテーブルエントリには、これらのエントリの 1 つが存在します。

DT_LOPROC - DT_HIPROC

この範囲の値は、プロセッサに固有の使用方法に対して予約されています。

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

次の表に示す動的状態フラグ DT_FLAGS が現在、使用可能です。

表 7-44 動的タグ DT_FLAGS

名前 

値 

意味 

DF_ORIGIN

0x1

$ORIGIN 処理が必要

DF_SYMBOLIC

0x2

シンボリックシンボル解決が必要 

DF_TEXTREL

0x4

テキストの再配置が存在する 

DF_BIND_NOW

0x8

非レイジー結合が必要 

DF_ORIGIN

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

DF_SYMBOLIC

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

DF_TEXTREL

このフラグが無いことは、再配置エントリが書き込み不可セグメント (プログラムヘッダーテーブル内のセグメントのアクセス権で指定される) に対する変更を発生させてはならないことを示します。このフラグが存在する場合は、1 つまたは複数の再配置エントリが書き込み不可セグメントに対する変更を要求する可能性があり、実行時リンカーはそれに応じて対応することができます。

DF_BIND_NOW

共有オブジェクトまたは実行可能ファイル内で設定された場合、このフラグは、プログラムに制御を渡す前にこのエントリを含むオブジェクトについてすべての再配置を処理するよう動的リンカーに指示します。環境で指定された、または dlopen(3DL) を介した場合、このエントリの存在は、このオブジェクトについてレイジー結合を使用するようにという指示よりも優先されます。この状態は、リンカーの -z now オプションを使用してオブジェクト内に記録されます。

次の表に示す動的状態フラグ DT_FLAGS_1 が現在、使用可能です。

表 7-45 動的タグ DT_FLAGS_1

名前 

値 

意味 

DF_1_NOW

0x1

完全な再配置処理を行います 

DF_1_GLOBAL

0x2

未使用 

DF_1_GROUP

0x4

オブジェクトがグループの構成要素であることを示します 

DF_1_NODELETE

0x8

オブジェクトがプロセスから削除できないことを示します 

DF_1_LOADFLTR

0x10

フィルティー (1 つまたは複数)の即時読み込みを保証します 

DF_1_INITFIRST

0x20

オブジェクトの初期化を最初に実行します 

DF_1_NOOPEN

0x40

オブジェクトを dlopen(3DL) で使用できません

DF_1_ORIGIN

0x80

$ORIGIN 処理が必要です

DF_1_DIRECT

0x100

直接結合が有効です 

DF_1_INTERPOSE

0x400

オブジェクトは割り込み処理です 

DF_1_NODEFLIB

0x800

デフォルトのライブラリ検索パスを無視します 

DF_1_NODUMP

0x1000

オブジェクトを dldump(3DL) でダンプできません

DF_1_CONFALT

0x2000

オブジェクトは代替構成です 

DF_1_ENDFILTEE

0x4000

フィルティーがフィルタの検索を終了します 

DF_1_DISPRELDNE

0x8000

ディスプレイスメント再配置の終了 

DF_1_DISPRELPND

0x10000

ディスプレイスメント再配置の保留 

DF_1_NOW

オブジェクトが読み込まれると、すべての再配置処理が行われます。「再配置が実行されるとき」を参照してください。この状態フラグは、リンカーの -z now オプションを使うことによって有効になります。

DF_1_GROUP

オブジェクトがグループの構成要素であることを示します。「シンボル検索」を参照してください。この状態フラグは、リンカーの -B group オプションを使うことによって有効になります。

DF_1_NODELETE

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

DF_1_LOADFLTR

この状態フラグは、「フィルタ」に対してのみ意味があります (「フィルタとしての共有オブジェクト」を参照)。フィルタが読み込まれると、関連付けられているすべてのフィルティーが直ちに処理されます (「フィルティーの処理」を参照)。この状態フラグは、リンカーの -z loadfltr オプションを使うことによってオブジェクトに有効になります。

DF_1_INITFIRST

オブジェクトが読み込まれると、このオブジェクトと共に読み込まれた他のオブジェクトより先に、このオブジェクトの初期化セクションが実行されます。「デバッギングエイド」を参照してください。この特殊な状態フラグは、libthread.so.1 で使用されることを意図しています。この状態フラグは、リンカーの -z initfirst オプションを使うことによって有効になります。

DF_1_NOOPEN

dlopen(3DL) を使ってオブジェクトを実行中プロセスに追加できないことを示します。この状態フラグは、リンカーの -z nodlopen オプションを使うことによってオブジェクトに有効になります。

DF_1_ORIGIN

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

DF_1_DIRECT

オブジェクトには、直接結合情報が存在します。「直接結合」を参照してください。

DF_1_INTERPOSE

オブジェクトシンボルテーブルは、起動性実行可能プログラム以外のすべてのシンボルの前に割り込みされます。この状態フラグは、リンカーの -z interpose オプションを使うことによって有効になります。「直接結合」 を参照してください。

DF_1_NODEFLIB

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

DF_1_NODUMP

このオブジェクトは dldump(3DL) によってダンプできません。このオプションの候補には、libdl.so.1 などのフィルタが含まれます。libdl.so.1 は、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

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

表 7-46 動的タグ DT_POSFLAG_1

名前 

値 

意味  

DF_P1_LAZYLOAD

0x1

後続のオブジェクトは、レイジーロードされる 

DF_P1_GROUPPERM

0x2

後続のオブジェクトは、グループパーミッションの状態でロードされる 

DF_P1_LAZYLOAD

後続の DT_* エントリは、読み込まれるオブジェクトを示します。このオブジェクトのローディングは、Syminfo テーブルエントリで示されるシンボル結合がこのオブジェクトを明確に参照するまで遅延されます。この状態は、リンカーの -z lazyload オプションを使用してオブジェクト内に記録されます。

DF_P1_GROUPPERM

後続の DT_* エントリは、読み込まれるオブジェクトを示します。このオブジェクト内のシンボルは、一般的なシンボル解決に対しては使用できません。このオブジェクト内のシンボルは、このオブジェクトを読み込ませたオブジェクト (1 つまたは複数) に対してのみ使用可能です。この状態は、リンカーの -z groupperm オプションを使用してオブジェクト内に記録されます。

表 7-47 に示す動的機能フラグが現在、使用可能です。

表 7-47 動的機能フラグ DT_FEATURE

名前 

値 

意味 

DTF_1_PARINIT

0x1

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

DTF_1_CONFEXP

0x2

構成ファイルが必要 (代替オブジェクトについては、crle(1) によって設定される。DF_1_CONFALT と同じ効果がある)

共有オブジェクトの依存性

実行時リンカーがオブジェクトファイルのメモリーセグメントを作成するとき、依存性 (動的構造体の DT_NEEDED エントリに記録される) は、プログラムのサービスを提供するためにどの共有オブジェクトが必要であるかを示します。参照された共有オブジェクトとそれが依存するものを繰り返し結合することによって、実行時リンカーは完全なプロセスイメージを生成します。

実行時リンカーは、記号参照を解決するとき、幅優先検索を使用してシンボルテーブルを調べます。つまり、実行時リンカーはまず実行可能プログラム自身のシンボルテーブルを参照し、次に DT_NEEDED エントリのシンボルテーブルを (順番に) 参照し、次に第 2 レベルの DT_NEEDED エントリといった具合に参照します。


注 -

共有オブジェクトが依存性リストにおいて複数回参照されるときでも、実行時リンカーはこの共有オブジェクトをプロセスに 1 回だけ結合します。


依存リストに示されている名前は、オブジェクトファイルの作成に使用される共有オブジェクトの DT_SONAME 文字列またはパス名です。

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

一般に位置に依存しないコードには絶対仮想アドレスは存在できません。大域オフセットテーブルには内部で使用するデータの絶対アドレスが存在しており、したがって、位置からの独立性とプログラムのテキストの共有性を低下させることなくアドレスが使用可能になります。プログラムは、位置に依存しないアドレス指定を使用して大域オフセットテーブルを参照し、絶対値を抜き出すことで位置に依存しない参照を、絶対位置に向け直します。

最初は、大域オフセットテーブルには再配置エントリで要求される情報が存在します (詳細は、「再配置」を参照)。システムが読み込み可能オブジェクトファイルのメモリーセグメントを作成した後、実行時リンカーが再配置エントリを処理します。これらの再配置エントリのいくつかは、R_SPARC_GLOB_DAT 型 (SPARC の場合) または R_386_GLOB_DAT 型 (IA の場合) であり、大域オフセットテーブルを参照します。

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

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

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

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

大域オフセットテーブルの形式と解釈は、プロセッサに固有です。SPARC プロセッサと IA プロセッサの場合、_GLOBAL_OFFSET_TABLE_ シンボルは、テーブルをアクセスするために使用できます。64 ビットコードの場合、シンボルタイプは Elf64_Addr の配列です。


extern Elf32_Addr _GLOBAL_OFFSET_TABLE_[];

シンボル _GLOBAL_OFFSET_TABLE_ は、.got セクションの中央に存在でき、その場合は、負の添字と負でない添字の両方がアドレスの配列になることができます。

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

大域オフセットテーブルは位置に依存しないアドレスの計算を絶対位置に変換するので、プロシージャのリンクテーブルは位置に依存しない関数呼び出しを絶対位置に変換します。リンカーは、ある 1 つの実行可能オブジェクトまたは共有オブジェクトから別の実行可能オブジェクトまたは共有オブジェクトへの実行転送 (関数呼び出しなど) を解決できません。したがって、リンカーはプログラム転送制御をプロシージャのリンクテーブルのエントリに与えます。

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

SPARC アーキテクチャの場合、プロシージャのリンクテーブルは私用 (private) データに存在します。実行時リンカーは、宛先の絶対アドレスを判定し、これらの絶対アドレスに従ってプロシージャのリンクテーブルのメモリーイメージに変更を加えます。このようにして実行時リンカーは、位置からの独立性とプログラムのテキストの共有性を低下させることなくエントリを向け直します。実行可能ファイルと共有オブジェクトファイルには、別個のプロシージャのリンクテーブルが存在します。

最初の 4 つのプロシージャのリンクテーブルエントリは、予約されます。テーブルの各エントリは 3 ワード (12 バイト) を占めており、最後のテーブルエントリの後には nop 命令が続きます。64 ビット SPARC オブジェクトの場合、各エントリは 8 つの命令 (32 バイト) を占めており、32 バイト境界で整列されなければなりません (テーブル全体は 256 バイト境界で整列されなければなりません)。

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

プロシージャのリンクテーブルの説明のため、表 7-48 は 4 つのエントリを示しています。最初の 2 つのエントリは予約されている最初の 4 つのエントリの内の 2 つであり、3 番目のエントリは name1 に対する呼び出しであり、4 番目のエントリは name2 に対する呼び出しです。この例では、name2 のエントリがテーブルの最後のエントリであることを前提としており、後に続く nop 命令が示されています。左欄は、動的リンクが行われる前のオブジェクトファイルの命令を示しています。右欄は、実行時リンカーがプロシージャのリンクテーブルエントリを修正することにしてとり得る方法を示しています。

表 7-48 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
	...
.PLT101:
	    sethi   (.-.PLT0),%g1
	    sethi   %hi(name1),%g1
	    jmp1    %g1+%lo(name1),%g0
.PLT102:
	    sethi   (.-.PLT0),%g1
	    sethi   %hi(name2),%g1
	    jmp1    %g1+%lo(name2),%g0
     nop
	    nop

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

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

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

  3. sethi 命令は、現在のプロシージャのリンクテーブルエントリと最初のプロシージャのリンクテーブルエントリの距離を計算する。つまり、.PLT101 と .PLT0 の距離を計算する。この値は、%g1 レジスタの最上位 22 ビットを占める。この例では、実行時リンカーが制御を受け取ると、%g1 には 0x12f000 が格納される

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

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

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

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

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

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

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

表 7-49 IA: プロシージャのリンクテーブルの例
.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
        ...
.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 再配置エントリ (プロシージャのリンクテーブルエントリ) を処理します。LD_BIND_NOW が空文字列の場合、実行時リンカーは、各テーブルエントリの最初の実行時にリンクテーブルエントリを評価します。

ハッシュテーブル

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

図 7-11 シンボルハッシュテーブル

Graphic

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

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

chain リンクから、求める名前のシンボルテーブルエントリを探すことができます。chain リンクの最後には STN_UNDEF が設定されます。


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;
}

初期設定関数および終了関数

実行時リンカーがプロセスイメージを作成し、再配置を行なった後、各共有オブジェクトと実行可能ファイルにはいくつかの初期設定関数を実行する機会があります。共有オブジェクトの初期設定はすべて、実行可能ファイルが制御を得る前に実行されます。

同様に、動的オブジェクトには終了関数が存在できます。終了関数は、元となるプロセスが終了手順を開始した後、またはそのオブジェクトが dlclose(3DL) により実行プロセスから削除された場合、atexit(3C) の機構で実行されます。詳細は、atexit(3C) のマニュアルページを参照してください。

動的オブジェクトは、表 7-43 に記述されているように、動的構造内の DT_INIT_ARRAY/DT_INIT および DT_FINI_ARRAY/DT_FINI エントリを介して初期設定関数および終了関数を指定します。

初期設定および終了についての詳細は、「初期設定および終了セクション」および 「初期設定および終了ルーチン」を参照してください。


注 -

atexit(3C) 終了処理は通常は行われますが、プロセス終了時に実行されることは保証されません。たとえば、プロセスが _exit() を呼び出した場合、またはプロセスが捕捉もされず無視もされない信号を受け取って終了した場合、プロセスは終了処理を実行しません。