リンカーとライブラリ

内部対応付け構造

ELF ベースのリンカーのもっとも重要なデータ構造の 1 つとして対応付け構造があります。上記で述べた初期値 mapfile に対応する初期対応付け構造は、コマンド実行時にリンカーで使われます。mapfile オプションが使われる場合、リンカーは mapfile を解析して、特定の値を初期対応付け構造に追加または上書きします。

一般的な (ただし多少簡略化した) 対応付け構造を図 8-1 に示します。「エントランス基準」ボックスは初期値の対応付け指示の情報に対応しており、「セグメント属性記述子」ボックスは、初期値のセグメント宣言の情報に対応しています。「出力記述子」ボックスは、各セグメントの下に来るセクションの詳細な属性を示します。セクション自体は丸で囲んであります。

図 8-1 簡単な対応付け構造

Graphic

リンカーはセクションをセグメントに対応付ける際に、以下の手順で行います。

  1. セクションを読み取る際に、リンカーは合致するものを見つけるために、一連のエントランス基準を検査します。指定したすべての条件が合致する必要があります。

    図 8-1 では、text セグメントに入るセクションの場合、section_type$PROGBITSsection_flags?A!W でなければなりません。エントランス基準では名前は指定されていないので、名前 .text は必要ありません。エントランス基準では実行ビットは何も指定されていないので、セクションは (section_flags 値の) X または !X のどちらかでもかまいません。

    エントランス基準に合致するものが見つからない場合、セクションはその他すべてのセグメントの後の a.out ファイルの最後に置かれます (この情報については、プログラムヘッダーエントリは作られません。詳細は、「プログラムヘッダー」を参照)。

  2. セクションがセグメントの中に入る際に、リンカーは以下のようにそのセグメントの既存の一連の出力セクション記述子を検査します。

    セクションの属性値が既存の出力セクション記述子の属性値とまったく合致する場合、セクションは出力セクション記述子に対応するセクションの列挙の最後に置かれます。

    たとえば、section_name.data1section_type$PROGBITS、および section_flags?AWX のセクションは、図 8-1 の 2 番目のエントランス基準ボックスにあてはまり、data セグメントに置かれます。セクションは 2 番目の出力セクション記述子ボックスにちょうど一致し (.data1$PROGBITS?AWX)、このボックスに対応する一連のセクションの最後に追加されます。fido.orover.o、および sam.o.data1 セクションは、このことを示しています。

    一致する出力セクション記述子が見つからず、同じ section_type の出力セクション記述子が他に存在する場合、セクションとして同じ属性値で新しい出力セクション記述子が作られ、そのセクションは新しい出力セクション記述子と対応づけられます。出力セクション記述子 (およびセクション) は、同じ section_type の最後の出力セクション記述子の後に置かれます。図 8-1.data2 セクションはこのやり方で置かれました。

    示された section_type の出力セクション記述子が他に存在しない場合、新しい出力セクション記述子が作られ、セクションはそのセクション内に置かれます。


    注 -

    入力セクションにユーザー定義の section_type が設定されている場合 (つまり、「セクション」で説明しているように、SHT_LOUSERSHT_HIUSER の間)、これは $PROGBITS セクションとして扱われます。mapfile でこの section_type 値に名前を付ける方法はありませんが、これらのセクションは、エントランス基準でその他の属性値指定 (section_flagssection_name) を使って付け直すことができます。


  3. すべてのコマンド行で指定されたオブジェクトファイルとライブラリが読み取られた後、セグメントがセクションをまったく含まない場合、そのセグメントに対してはプログラムヘッダーエントリは作られません。


    注 -

    $SYMTAB$STRTAB$REL、および $RELA 型の入力セクションは、リンカーにより内部で使用されます。これらの section_type を参照する指示は、リンカーで作った出力セクションしかセグメントに対応付けできません。