リンカーとライブラリ

シンボルテーブル

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

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

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

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

この構造体の要素を次に示します。

st_name

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

st_value

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

st_size

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

st_info

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

#define ELF32_ST_BIND(info)          ((info)>> 4)
#define ELF32_ST_TYPE(info)          ((info) & 0xf)
#define ELF32_ST_INFO(bind, type)    (((bind)<<4)+((type)&0xf))

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

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

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

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

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

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

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

名前 

値 

STB_LOCAL

0

STB_GLOBAL

1

STB_WEAK

2

STB_LOOS

10

STB_HIOS

12

STB_LOPROC

13

STB_HIPROC

15

STB_LOCAL

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

STB_GLOBAL

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

STB_WEAK

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

STB_LOOS - STB_HIOS

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

STB_LOPROC - STB_HIPROC

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

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


注 –

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


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

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

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

名前 

値 

STT_NOTYPE

0

STT_OBJECT

1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_COMMON

5

STT_TLS

6

STT_LOOS

10

STT_HIOS

12

STT_LOPROC

13

STT_SPARC_REGISTER

13

STT_HIPROC

15

STT_NOTYPE

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

STT_OBJECT

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

STT_FUNC

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

STT_SECTION

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

STT_FILE

慣例により、シンボルの名前はオブジェクトファイルに対応するソースファイルの名前を与えます。ファイルシンボルは STB_LOCAL に結び付けられており、セクションインデックスは SHN_ABS です。このシンボルは、存在する場合、ファイルの他の STB_LOCAL シンボルの前に存在します。 SHT_SYMTAB のシンボルインデックス 1 は、ファイル自身を表す STT_FILE シンボルです。慣例により、この後にはファイルの STT_SECTION シンボルと、ローカルシンボルに短縮されている大域シンボルが続きます。

STT_COMMON

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

STT_TLS

シンボルは、スレッド固有領域の実体を指定します。定義されている場合、実際のアドレスではなく、シンボルに割り当てられたオフセットを提供します。STT_TLS 型のシンボルは、特殊なスレッド固有領域の再配置だけによって参照され、スレッド固有領域の再配置は、STT_TLS 型のシンボルだけを参照します。詳細は、スレッド固有領域 を参照してください。

STT_LOOS - STT_HIOS

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

STT_LOPROC - STT_HIPROC

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

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

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

名前 

値 

STV_DEFAULT

0

STV_INTERNAL

1

STV_HIDDEN

2

STV_PROTECTED

3

STV_DEFAULT

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

STV_PROTECTED

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

STV_HIDDEN

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

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

STV_INTERNAL

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

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

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

SHN_ABS

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

SHN_COMMON

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

SHN_UNDEF

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

すでに説明したように、インデックス 0 (STN_UNDEF) のシンボルテーブルエントリは予約されています。このエントリは以下の値を保持します。

表 7–22 ELF シンボルテーブルエントリ: インデックス 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–23 SPARC: ELF シンボルテーブルエントリ: レジスタシンボル

フィールド 

意味 

st_name

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

st_value

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

st_size

未使用 (0)  

st_info

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

st_other

未使用 (0)  

st_shndx

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

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

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

名前 

値 

意味 

STO_SPARC_REGISTER_G2

0x2

%g2

STO_SPARC_REGISTER_G3

0x3

%g3

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