リンカーとライブラリ

サポートインタフェース関数

「ld-サポートインタフェース」はすべて、ヘッダーファイル link.h に定義されています。インタフェース引数はすべて、基本的な C タイプまたは ELF タイプです。 ELF データタイプは、ELF アクセスライブラリ libelf を使用して確認できます。libelf の詳細は、elf(3ELF) のマニュアルページを参照してください。次のインタフェース関数が「ld-サポート」インタフェースにより提供されます。各インタフェース関数は、使用順序に従って記載されています。

ld_version()

この関数は、リンカーとサポートライブラリとの間の初期ハンドシェークを提供します。

uint_t ld_version(uint_t version);

リンカーは、リンカーがサポート可能な最新バージョンの「ld-サポート」インタフェースを使用して、このインタフェースを呼び出します。サポートライブラリは、このバージョンが使用するのに十分かどうかを確認できます。次に、サポートライブラリは、サポートライブラリが使用する予定のバージョンを返すことができます。通常、このバージョンは LD_SUP_VCURRENT です。

サポートライブラリがこのインタフェースを提供しない場合、初期サポートレベルは LD_SUP_VERSION1 と見なされます。

サポートライブラリがゼロのバージョン、またはリンカーがサポートする ld-サポートインタフェースよりも大きい値を返す場合、サポートライブラリは使用されません。

ld_start()

この関数は、リンカーコマンド行の初期妥当性検査のあとに呼び出されます。この関数は、入力ファイル処理の開始を示します。

void ld_start(const char * name, const Elf32_Half type,
        const char * caller);

void ld_start64(const char * name, const Elf64_Half type,
        const char * caller);

nameは、作成される出力ファイル名を示します。type は出力ファイルタイプであり、ET_DYNET_RELET_EXEC のいずれかで、これは sys/elf.h に定義されています。caller はインタフェースを呼び出すアプリケーションを示し、これは通常、/usr/ccs/bin/ld です。

ld_open()

この関数は、リンク編集への各入力ファイルに対して呼び出されます。バージョン LD_SUP_VERSION3 で追加されたこの関数は、ld_file() 関数よりも高い柔軟性を備えています。サポートライブラリはこの関数を使用することで、ファイル記述子、ELF 記述子、およびそれらに関連付けられたファイル名を置き換えることができます。この関数は次のシナリオで使用できます。

  • 既存の ELF ファイルへの新しいセクションの追加。この場合、元の ELF 記述子を、ELF ファイルの更新を可能とする記述子で置き換えるようにしてください。elf_begin(3ELF)ELF_C_RDWR 引数を参照してください。

  • 入力ファイルの全体を別のファイルで置き換え可能。この場合、元のファイル記述子と ELF 記述子を、新しいファイルに関連付けられた記述子で置き換えるようにしてください。

どちらのシナリオの場合も、パス名とファイル名を別の名前で置き換えることができ、そうした場合、それは入力ファイルが変更されたことを示します。

void ld_open(const char ** pname, const char ** fname, int * fd,
	int flags, Elf ** elf, Elf * ref, size_t off, Elf_Kind kind);
void ld_open64(const char ** pname, const char ** fname, int * fd,
	int flags, Elf ** elf, Elf * ref, size_t off, Elf_Kind kind);

pname は、処理されようとしている入力ファイルのパス名です。fname は、処理されようとしている入力ファイルのファイル名です。fname は通常、pname のベース名になります。pnamefname はどちらも、サポートライブラリから変更できます。

fd は、入力ファイルのファイル記述子です。サポートライブラリからこの記述子を閉じ、新しいファイル記述子をリンカーに返せます。値が -1 のファイル記述子を返せば、そのファイルを無視すべきであることを示せます。


注 –

ld_open() に渡された fd には、リンカーがld_open() でファイル記述子を閉じることができないと、値 -1 が設定されます。この状況が発生するもっとも一般的な理由は、アーカイブメンバーの処理の場合です。値 -1ld_open() に渡されると、記述子を閉じることができなくなり、代替の記述子がサポートライブラリから返されなくなります。


flags フィールドは、リンカーによるファイルの取得方法を示します。このフィールドには、次の定義の 1 つまたは複数を指定できます。

  • LD_SUP_DERIVED – ファイル名がコマンド行に明示的に指定されませんでした。ファイルは、-l を展開して派生されました。あるいは、ファイルは、抽出されたアーカイブメンバーです。

  • LD_SUP_EXTRACTED – ファイルはアーカイブから抽出されました。

  • LD_SUP_INHERITED – ファイルはコマンド行の共有オブジェクトの依存関係として取得されました。

flags 値が指定されていない場合は、入力ファイルがコマンド行に明示的に指定されました。

elf は、入力ファイルの ELF 記述子です。サポートライブラリからこの記述子を閉じ、新しい ELF 記述子をリンカーに返せます。値が 0 の ELF 記述子を返すことができ、そのファイルを無視すべきであることを示せます。elf 記述子がアーカイブライブラリのメンバーに関連付けられている場合、ref 記述子はその背後のアーカイブファイルの ELF 記述子になります。off は、アーカイブファイル内のアーカイブメンバーのオフセットを表します。

kind は入力ファイルのタイプを示し、libelf.h に定義されているように ELF_K_AR または ELF_K_ELF のいずれかになります。

ld_file()

この関数は、リンク編集への各入力ファイルに対して呼び出されます。この関数は、ファイルデータの処理が実行される前に呼び出されます。

void ld_file(const char * name, const Elf_Kind kind, int flags,
        Elf * elf);

void ld_file64(const char * name, const Elf_Kind kind, int flags,
        Elf * elf);

name は処理される入力ファイルを示します。kind は入力ファイルのタイプを示し、libelf.h に定義されているように ELF_K_AR または ELF_K_ELF のいずれかになります。flags フィールドは、リンカーによるファイルの取得方法を示します。このフィールドには、ld_open()flags フィールドと同じ定義を含めることができます。

  • LD_SUP_DERIVED – ファイル名がコマンド行に明示的に指定されませんでした。ファイルは、-l を展開して派生されました。あるいは、ファイルは、抽出されたアーカイブメンバーです。

  • LD_SUP_EXTRACTED – ファイルはアーカイブから抽出されました。

  • LD_SUP_INHERITED – ファイルはコマンド行の共有オブジェクトの依存関係として取得されました。

flags 値が指定されていない場合は、入力ファイルがコマンド行に明示的に指定されました。

elf は、入力ファイルの ELF 記述子です。

ld_input_section()

この関数は、入力ファイルの各セクションに対して呼び出されます。この関数は、リンカーがそのセクションを出力ファイルに送信することを決定する前に呼び出されます。これは、バージョン LD_SUP_VERSION2 で追加された関数です。これは、出力ファイルに寄与するセクションに対してのみ呼び出される、ld_section() 処理とは異なります。

void ld_input_section(const char * name, Elf32_Shdr ** shdr,
        Elf32_Word sndx, Elf_Data * data, Elf * elf, unit_t flags);

void ld_input_section64(const char * name, Elf64_Shdr ** shdr,
        Elf64_Word sndx, Elf_Data * data, Elf * elf, uint_t flags);

name は、入力セクション名を示します。shdr は、関連のセクションヘッダーへのポインタを示します。sndx は、入力ファイル内のセクションインデックスです。data は、関連データバッファーへのポインタを示します。elf は、ファイル ELF 記述子へのポインタです。flags は、将来の使用のために予約されています。

セクションヘッダーの再割り当ておよび *shdr への代入によるセクションヘッダーの変更は許されています。リンカーは、ld_input_section() から戻った後で、*shdr が指し示すセクションヘッダー情報を使用して、セクションを処理します。

データを再割り当てし、Elf_Data バッファーの d_buf ポインタに代入してデータを変更できます。データを変更する場合、Elf_Data バッファーの d_size 要素を正しく設定しなければなりません。出力イメージの一部になる入力セクションでは、d_size 要素をゼロに設定すると、出力イメージからデータが実際に削除されます。

flags フィールドは、初期値にゼロが設定される uint_t データフィールドを指します。フラグは、将来のアップデートでリンカーやサポートライブラリが割り当てできるように提供はされていますが、現在のところは割り当てられていません。

ld_section()

この関数は、出力ファイルに送信される入力ファイルのセクションごとに呼び出されます。この関数は、セクションデータの処理が実行される前に呼び出されます。

void ld_section(const char * name, Elf32_Shdr * shdr,
        Elf32_Word sndx, Elf_Data * data, Elf * elf);

void ld_section64(const char * name, Elf64_Shdr * shdr,
        Elf64_Word sndx, Elf_Data * data, Elf * elf);

name は、入力セクション名を示します。shdr は、関連のセクションヘッダーへのポインタを示します。sndx は、入力ファイル内のセクションインデックスです。data は、関連データバッファーへのポインタを示します。elf は、ファイル ELF 記述子へのポインタです。

データを再割り当てし、Elf_Data バッファーの d_buf ポインタに代入してデータを変更できます。データを変更する場合、Elf_Data バッファーの d_size 要素を正しく設定しなければなりません。出力イメージの一部になる入力セクションでは、d_size 要素をゼロに設定すると、出力イメージからデータが実際に削除されます。


注 –

出力ファイルから取り除かれるセクションは、ld_section() に報告されません。セクションは、リンカーの -s オプションを使って取り除かれます。セクションは、SHT_SUNW_COMDAT 処理や SHF_EXCLUDE の識別によって破棄されます。「「COMDAT」セクション」表 7–8 を参照してください。


ld_input_done()

この関数は、入力ファイルの処理が完了してから、出力ファイルの配置が実行されるまでに呼び出されます。これは LD_SUP_VERSION2 で追加された関数です。

void ld_input_done(uint_t * flags);

flags フィールドは、初期値にゼロが設定される uint_t データフィールドを指します。フラグは、将来のアップデートでリンカーやサポートライブラリが割り当てできるように提供はされていますが、現在のところは割り当てられていません。

ld_atexit()

この関数は、リンク編集の完了時に呼び出されます。

void ld_atexit(int status);

void ld_atexit64(int status);

status は、リンカーによって返される exit(2) コードであり、stdlib.h に定義されているように、EXIT_FAILURE または EXIT_SUCCESS のいずれかになります。