オブジェクトファイルのシンボルテーブルは、プログラムのシンボル定義/参照の探索と再配置に必要な情報を保持します。シンボルテーブルインデックスは、この配列への添字です。インデックス 0 はシンボルテーブルの先頭エントリを指定し、また未定義シンボルインデックスとして機能します。先頭エントリの内容は、このセクションの後の方で記述します。
表 7-18 シンボルテーブルの先頭エントリ
名前 |
値 |
---|---|
STN_UNDEF |
0 |
シンボルテーブルエントリの形式 (sys/elf.h で定義されている) は、次のとおりです。
typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_Sym; typedef struct { Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym; |
この構成要素は、オブジェクトファイルのシンボル文字列テーブルへのインデックス (シンボル名の文字表現を保持する) を保持します。値が 0 以外の場合、その値はシンボル名を与える文字列テーブルインデックスを表します。値が 0 の場合、シンボルテーブルエントリに名前は存在しません。
外部 C シンボルは、C とオブジェクトファイルのシンボルテーブルにおいて同じ名前を持ちます。
この構成要素は、関連付けられているシンボルの値を与えます。この値は、絶対値やアドレスなど (状況に依存する) を表します。「シンボル値」を参照してください。
多くのシンボルは、関連付けられている大きさを持っています。たとえば、データオブジェクトのサイズは、データオブジェクトに存在するバイト数です。この構成要素は、シンボルが大きさを持っていない場合または大きさが不明な場合、0 を保持します。
この構成要素は、シンボルの種類と結び付けられる属性を指定します。値と意味のリストを以下に示します。次のコードは、値 (sys/elf.h で定義されている) の処理方法を示します。
#define ELF32_ST_BIND(i) ((i) >> 4) #define ELF32_ST_TYPE(i) ((i) & 0xf) #define ELF32_ST_INFO(b, t) (((b)<<4)+((t)&0xf)) #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) #define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) |
この構成要素は現在 0 を保持しており、意味は定義されていません。
すべてのシンボルテーブルエントリは、何らかのセクションに関して定義されます。この構成要素は、該当するセクションヘッダーテーブルインデックスを保持します。いくつかのセクションインデックスは、特別な意味を示します。表 7-12 を参照してください。
名前 |
値 |
---|---|
STB_LOCAL |
0 |
STB_GLOBAL |
1 |
STB_WEAK |
2 |
STB_LOPROC |
13 |
STB_HIPROC |
15 |
局所シンボルは、局所シンボルの定義が存在するオブジェクトファイルの外部では見えません。同じ名前の局所シンボルは、互いに干渉することなく複数のファイルに存在できます。
大域シンボルは、結合されるすべてのオブジェクトファイルで見ることができます。あるファイルの大域シンボルの定義は、その大域シンボルへの別ファイルの未定義参照を解決します。
ウィークシンボルは大域シンボルに似ていますが、ウィークシンボルの定義の優先順位は大域シンボルの定義より低いです。
この範囲の値は、プロセッサ固有の使用方法に対して予約されます。
大域シンボルとウィークシンボルは、主に 2 つの点で異なります。
リンカーは、いくつかの再配置可能オブジェクトファイルを結合するとき、同じ名前の STB_GLOBAL シンボルの複数の定義を許しない。一方、定義された大域シンボルが存在している場合、同じ名前のウィークシンボルが現れてもエラーは発生しない。リンカーは大域定義を使用し、弱い定義を無視する
同様に、共通シンボルが存在している場合 (つまり、SHN_COMMON を保持している st_index フィールドが存在するシンボルが存在している場合)、同じ名前のウィークシンボルが現れてもエラーは発生しない。リンカーは共通定義を使用し、弱い定義を無視する
リンカーは、アーカイブライブラリ (「アーカイブ処理」を参照) を検索するとき、大域シンボル (未定義または一時的) の定義が存在するアーカイブ構成要素を抜き出す。構成要素の定義は、大域シンボルまたはウィークシンボル
リンカーはデフォルトでは、未定義のウィークシンボルを解決するためのアーカイブ構成要素を抜き出さない。解決されていないウィークシンボルは、値 0 を持ち。-z weakextract を使用すると、このデフォルトの動作が無効になり、弱い参照がアーカイブ構成要素を抜き出すことができる。
各シンボルテーブルにおいて、STB_LOCAL 結び付きが存在するすべてのシンボルは、ウィークシンボルと大域シンボルの前に存在します。「セクション」に記述されているとおり、シンボルテーブルセクションの sh_info セクションヘッダー構成要素は、最初の局所的ではないシンボルに対するシンボルテーブルインデックスを保持します。
シンボルの種類は、関連付けられている実体に関する一般的分類を行います。
表 7-20 シンボルの種類 (ELF32_ST_TYPE、ELF64_ST_TYPE)
名前 |
値 |
---|---|
STT_NOTYPE |
0 |
STT_OBJECT |
1 |
STT_FUNC |
2 |
STT_SECTION |
3 |
STT_FILE |
4 |
STT_LOPROC |
13 |
STT_SPARC_REGISTER |
13 |
STT_HIPROC |
15 |
シンボルの種類は指定されません。
シンボルは、データオブジェクト (変数や配列など) と関連付けられています。
シンボルは、関数または他の実行可能コードに関連付けられています。
シンボルは、セクションに関連付けられています。この種類のシンボルテーブルエントリは主に再配置を行うために存在しており、通常、STB_LOCAL に結び付けられています。
慣例により、シンボルの名前はオブジェクトファイルに対応するソースファイルの名前を与えます。ファイルシンボルは STB_LOCAL に結び付けられており、セクションインデックスは SHN_ABS であり、ファイルシンボル (存在する場合) はファイルの他の STB_LOCAL シンボルの前に存在します。SHT_SYMTAB のシンボルインデックス 1 は、ファイル自身を表す STT_FILE シンボルです。慣例により、この後にはファイルの STT_SECTION シンボルと、局所シンボルに短縮されている大域シンボルが続きます (詳細は、「シンボル範囲の縮小」と、第 5 章「バージョンアップ」を参照してください。)
この範囲の値は、プロセッサ固有の使用方法に対して予約されます。
共有オブジェクトファイルの関数シンボル (STT_FUNC タイプが存在する) は、特別な意味を持っています。別のオブジェクトファイルが共有オブジェクトの関数を参照すると、リンカーは参照されるシンボルの手続きリンクテーブルエントリを自動的に作成します。STT_FUNC 以外のタイプの共有オブジェクトシンボルは、手続きリンクテーブルから自動的には参照されません。
シンボル値がセクション内の特定位置を参照すると、セクションインデックス構成要素 st_shndx は、セクションヘッダーテーブルへのインデックスを保持します。再配置時にセクションが移動すると、シンボル値も変化し、シンボルへの参照はプログラム内の同じ位置を指し示し続けます。いくつかの特別なセクションインデックス値は、他の意味付けがされています。
シンボルは、絶対値 (再配置が行われても変化しない) を持ちます。
シンボルは、割り当てられていない共通ブロックを示します。シンボル値は、セクションの sh_addralign 構成要素に類似した整列制約を与えます。つまり、リンカーは st_value の倍数のアドレスにシンボル記憶領域を割り当てます。シンボルの大きさは、必要なバイト数を示します。
このセクションテーブルインデックスは、シンボルが未定義であることを意味します。リンカーがこのオブジェクトファイルを、示されたシンボルを定義する他のオブジェクトファイルに結合すると、このシンボルに対するこのファイルの参照は実際の定義に結び付けられます。
前述したとおり、インデックス 0 (STN_UNDEF) のシンボルテーブルエントリは予約されています。このシンボルテーブルエントリは以下の値を保持します。
表 7-21 シンボルテーブルエントリ: インデックス 0
名前 |
値 |
注意 |
---|---|---|
st_name |
0 |
名前はない |
st_value |
0 |
値は 0 |
st_size |
0 |
サイズはない |
st_info |
0 |
種類はない。局所結び付き |
st_other |
0 |
|
st_shndx |
SHN_UNDEF |
セクションは存在しない |
異なる複数のオブジェクトファイル型のシンボルテーブルエントリは、st_value 構成要素に対してわずかに異なる解釈を持ちます。
再配置可能ファイルでは、st_value はセクションインデックスが SHN_COMMON であるシンボルに対する整列制約を保持する
再配置可能ファイルでは、st_value は定義されたシンボルに対するセクションオフセットを保持する。つまり、st_value は、st_shndx が識別するセクションの先頭からのオフセット
実行可能オブジェクトファイルと共有オブジェクトファイルでは、st_value は仮想アドレスを保持する。これらのファイルのシンボルを実行時リンカーに対してより有用にするために、セクションオフセット (ファイル解釈) の代わりに、セクション番号が無関係な仮想アドレス (ファイル解釈) が使用される
シンボルテーブル値は、異なる種類のオブジェクトファイルでも似た意味を持ちますが、適切なプログラムはデータに効率的にアクセスできます。
SPARC アーキテクチャは、レジスタシンボル (大域レジスタを初期化するシンボル) をサポートします。レジスタシンボルに対するシンボルテーブルエントリには、以下の値が入ります。
表 7-22 シンボルテーブルエントリ: レジスタシンボル
フィールド |
意味 |
---|---|
st_name |
シンボル名文字列テーブルへのインデックス。または 0 (スクラッチレジスタ) |
st_value |
レジスタ番号。整数レジスタの割り当てについては、ABI マニュアルを参照 |
st_size |
未使用 (0) |
st_info |
結び付きは標準的には STB_GLOBAL。種類は STT_SPARC_REGISTER でなければならない |
st_other |
未使用 (0) |
st_shndx |
SHN_ABS (このオブジェクトがこのレジスタシンボルを初期化する場合)。SHN_UNDEF (それ以外の場合) |
表 7-23 SPARC レジスタ番号
名前 |
値 |
意味 |
---|---|---|
STO_SPARC_REGISTER_G2 |
0x2 |
%g2 |
STO_SPARC_REGISTER_G3 |
0x3 |
%g3 |
特定の大域レジスタのエントリが存在しないことは、その特定の大域レジスタがオブジェクトで使用されないことを意味します。