リンカーとライブラリ

出力ファイルの生成

入力ファイルの処理とシンボル解決がすべて重大なエラーが発生することもなく完了すると、リンカーは出力ファイルを生成します。リンカーは、出力ファイルの完成に必要な追加セクションをまず生成します。これらのセクションには、すべての入力ファイルから解決済みの大域およびウィークシンボル情報とともに局所シンボル定義を含むシンボルテーブルが含まれます。

また、実行時リンカーが必要とする、出力の再配置および動的情報セクションも組み込まれます。すべての出力セクション情報が設定された後、出力ファイルサイズの合計が計算されます。次に出力ファイルイメージが適宜作成されます。

動的実行可能プログラムまたは共有オブジェクトを作成するときに、通常、2 つのシンボルテーブルが生成されます。.dynsym とその関連文字列テーブル .dynstr には、レジスタ、大域シンボル、ウィークシンボル、およびセクションシンボルが組み込まれます。これらのセクションは、実行時処理イメージの一部としてマッピングされる text セグメントの一部となります。mmap(2) のマニュアルページを参照してください。このマッピングにより、実行時リンカーは、これらのセクションを読み取り、必要な再配置を実行できます。

.symtab とその関連文字列テーブル .strtab には、入力ファイル処理から収集されたすべてのシンボルが含まれています。これらのセクションは、プロセスイメージの一部として対応付けられません。これらのセクションは、リンカーの -s オプションを使用して、または、リンク編集後に strip(1) を使用して、イメージから取り除くことさえ可能です。

予約シンボルは、シンボルテーブルの生成中に作成されます。これらのシンボルは、リンクプロセスに対して特別な意味を持っています。コードでは、これらのシンボルを定義しないでください。

_etext

すべての読み取り専用情報のあとの最初の場所は、一般にテキストセグメントと呼ばれます。

_edata

初期化されたデータのあとの最初の位置。

_end

すべてのデータのあとの最初の位置。

_DYNAMIC

.dynamic 情報セクションのアドレス。

_END_

_end と同じ。このシンボルは、_START_ シンボルとともに、ローカル範囲を持ち、オブジェクトのアドレス範囲を確立する簡単な手段を提供します。

_GLOBAL_OFFSET_TABLE_

リンカーが提供するアドレステーブル ( .got セクション) への位置独立の参照。このテーブルは、-K pic オプションを指定してコンパイルしたオブジェクトで発生する、位置独立のデータ参照から構築されます。「位置独立のコード」を参照してください。

_PROCEDURE_LINKAGE_TABLE_

リンカーが提供するアドレステーブル (.plt セクション) への、位置独立の参照。このテーブルは、-K pic オプションを指定してコンパイルしたオブジェクトで発生する、位置独立の関数参照から構築されます。「位置独立のコード」を参照してください。

_START_

テキストセグメント内の最初の位置。このシンボルは、_END_ シンボルとともに、ローカル範囲を持ち、オブジェクトのアドレス範囲を確立する簡単な手段を提供します。

リンカーは、実行可能ファイルを生成する場合、追加シンボルを検出して実行可能ファイルのエントリポイントを定義します。シンボルがリンカーの -e オプションを使用して指定された場合、そのシンボルが使用されます。それ以外の場合は、リンカーは予約シンボル名 _startmain を検出します。

ハードウェアとソフトウェア機能の特定

再配置可能オブジェクトのハードウェア機能とソフトウェア機能は、一般的にコンパイル時に記録されます。リンカーは入力再配置可能オブジェクトの機能を組み合わせて、出力ファイルの最終機能セクションを作成します。「ハードウェアおよびソフトウェア機能に関するセクション」を参照してください。

さらに、リンカーが出力ファイルを作成するときにも機能を定義できます。これらの機能は、mapfile とリンカーの -M オプションを使用して特定します。mapfile を使用して定義した機能は、入力再配置可能オブジェクトから提供される機能を増強したり、無効にしたりすることができます。

次の節では、mapfile を使用して機能を定義する方法を説明します。

ハードウェア機能の特定

オブジェクトのハードウェア機能は、オブジェクトを正しく実行するために必要なプラットフォームのハードウェア要件を特定します。この要件の例としては、一部の x86 アーキテクチャーで利用できる MMX または SSE を必要とするコードの特定があります。

ハードウェア機能要件は、次の mapfile 構文を使用して特定できます。


hwcap_1 = TOKEN | Vval [ OVERRIDE ];

hwcap_1 宣言は 1 つ以上のトークンで修飾されます。これはハードウェア機能のシンボル表現です。さらに、別の方法として、より多くの機能の 1 つを表す数値に V という接頭辞をつけて指定できます。SPARC プラットフォームでは、ハードウェア機能は sys/auxv_SPARC.hAV_ の値として定義されます。x86 プラットフォームでは、ハードウェア機能は sys/auxv_386.hAV_ の値として定義されます。

次の x86 の例では、オブジェクト foo.so.1 に必要なハードウェア機能として MMXSSE が宣言されています。


$ egrep "MMX|SSE" /usr/include/sys/auxv_386.h
#define AV_386_MMX    0x0040
#define AV_386_SSE    0x0800
$ cat mapfile
hwcap_1 = SSE MMX;
$ cc -o foo.so.1 -G -K pic -Mmapfile foo.c -lc
$ elfdump -H foo.so.1

Hardware/Software Capabilities Section:  .SUNW_cap
     index  tag               value
       [0]  CA_SUNW_HW_1     0x840  [ SSE  MMX ]

再配置可能オブジェクトには、ハードウェア機能の値を含めることができます。リンカーは、複数の入力再配置可能オブジェクトからのハードウェア機能値を組み合わせます。この結果生じる CA_SUNW_HW_1 の値は、関連入力値のビット単位の OR となります。デフォルトでは、これらの値は、mapfile で指定されたハードウェア機能と組み合わせられます。

出力ファイルのハードウェア機能要件は、OVERRIDE キーワードを使用して mapfile から明示的に制御できます。OVERRIDE キーワードは、ハードウェア機能値 0 とともに、構築中のオブジェクトからハードウェア機能要件を事実上削除します。


$ elfdump -H foo.o

Hardware/Software Capabilities Section:  .SUNW_cap
     index  tag               value
       [0]  CA_SUNW_HW_1     0x840  [ SSE  MMX ]
$ cat mapfile
hwcap_1 = V0x0 OVERRIDE;
$ cc -o bar.o -r -Mmapfile foo.o
$ elfdump -H bar.o
$ 

オブジェクトが定義したハードウェア機能要件は、実行時リンカーによってプロセスで利用できるハードウェア機能に対して検証されます。ハードウェア機能要件の一部を満足できない場合、そのオブジェクトは実行時に読み込みされません。たとえば、SSE 機能がプロセスで利用できない場合、ldd(1) は次のエラーを示します。


$ ldd prog
        foo.so.1 =>      ./foo.so.1  - hardware capability unsupported: \
                         0x800 [ SSE ]
        ....

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

ソフトウェア機能の特定

オブジェクトのソフトウェア機能は、プロセスのデバッグまたは監視にとって重要なことがあるソフトウェアの特徴を特定します。現在、認識されているソフトウェア機能だけが、オブジェクトによるフレームポインタ使用に関係します。

オブジェクトは、フレームポインタ使用を認識することを示せます。この状態は、フレームポインタを使用中または未使用として宣言することで、修飾されます。

ソフトウェア機能フラグは、sys/elf.h で定義されています。

#define  SF1_SUNW_FPKNWN    0x001
#define  SF1_SUNW_FPUSED    0x002

これらのソフトウェア機能要件は、次の mapfile 構文を使用して特定できます。


sfcap_1 = TOKEN | Vval [ OVERRIDE ];

sfcap_1 の宣言は、トークン FPKNWNFPUSED で修飾できます。または、これらの状態を表す数値を代わりに使用することもできます。

再配置可能オブジェクトには、ソフトウェア機能の値を含めることができます。リンカーは、複数の入力再配置可能オブジェクトからのソフトウェア機能値を組み合わせます。ソフトウェア機能は、mapfile も提供されます。デフォルトでは、mapfile のすべての値が、再配置可能オブジェクトで提供される値と組み合わせられます。

出力ファイルのソフトウェア機能要件は、OVERRIDE キーワードを使用して mapfile から明示的に制御できます。OVERRIDE キーワードは、ソフトウェア機能値 0 とともに、構築中のオブジェクトからソフトウェア機能要件を事実上削除します。


$ elfdump -H foo.o

Hardware/Software Capabilities Section:  .SUNW_cap
     index  tag               value
       [0]  CA_SUNW_SF_1     0x3  [ SF1_SUNW_FPKNWN  SF1_SUNW_FPUSED ]
$ cat mapfile
sfcap_1 = V0x0 OVERRIDE;
$ cc -o bar.o -r -Mmapfile foo.o
$ elfdump -H bar.o
$ 

ソフトウェア機能フレームポインタの処理

2 つのフレームポインタ入力値からの CA_SUNW_SF_1 値は、次のように計算されます。

表 2–1 CA_SUNW_SF_1 フレームポインタフラグ組み合わせ状態テーブル

入力ファイル 1 

入力ファイル 2 

 

SF1_SUNW_FPKNWN SF1_SUNW_FPUSED

SF1_SUNW_FPKNWN

<unknown>

SF1_SUNW_FPKNWN SF1_SUNW_FPUSED

SF1_SUNW_FPKNWN SF1_SUNW_FPUSED

SF1_SUNW_FPKNWN

SF1_SUNW_FPKNWN SF1_SUNW_FPUSED

SF1_SUNW_FPKNWN

SF1_SUNW_FPKNWN

SF1_SUNW_FPKNWN

SF1_SUNW_FPKNWN

<unknown>

SF1_SUNW_FPKNWN SF1_SUNW_FPUSED

SF1_SUNW_FPKNWN

<unknown>

この計算は、再配置可能オブジェクト値と mapfile 値にそれぞれ適用されます。.SUNW_cap セクションが存在しない場合や、このセクションに CA_SUNW_SF_1 の値が含まれない場合、SF1_SUNW_FPKNW フラグも SF1_SUNW_FPUSED フラグも設定されていない場合は、オブジェクトのフレームポインタソフトウェア機能は不明になります。