標準フィルタを生成するには、まずフィルタ処理を適用する「フィルティー」を定義する必要があります。次の例では、シンボル foo と bar を提供する「フィルティー」filtee.so.1 を構築します。
$ cat filtee.c char * bar = "defined in filtee"; char * foo() { return("defined in filtee"); } $ cc -o filtee.so.1 -G -K pic filtee.c |
標準フィルタ処理は、2 つの方法のいずれかで実行できます。共有オブジェクトによって提供されるすべてのインタフェースをフィルタとして宣言するには、リンカーの -F フラグを使用します。フィルタとなる共有オブジェクトの個々のインタフェースを宣言するには、リンカーの mapfile と FILTER キーワードを使用します。
次の例では、共有オブジェクト filter.so.1 がフィルタとして定義されています。filter.so.1 はシンボル foo と bar を提供し、それ自体が「フィルティー」filtee.so.1 のフィルタです。この例では、コンパイラドライバが -F オプションを解釈しないように、環境変数 LD_OPTIONS が使用されています。
$ cat filter.c char * bar = NULL; char * foo() { return (NULL); } $ LD_OPTIONS='-F filtee.so.1' \ cc -o filter.so.1 -G -K pic -h filter.so.1 -R. filter.c $ elfdump -d filter.so.1 | egrep "SONAME|FILTER" [2] SONAME 0xee filter.so.1 [3] FILTER 0xfb filtee.so.1 |
動的実行可能ファイルまたは共有オブジェクトを作成する場合、リンカーは標準フィルタ filter.so.1 を依存関係として参照できます。リンカーは、フィルタのシンボルテーブルの情報を使用してシンボル解決を行います。しかし、実行時にフィルタのシンボルを参照すると、必ず「フィルティー」filtee.so.1 がさらに読み込まれます。実行時リンカーはこの「フィルティー」を使用して、filter.so.1 によって定義されたシンボルを解決します。この「フィルティー」が見つからないか、あるいは「フィルティー」内にフィルタシンボルが見つからない場合は、このシンボル検索でそのフィルタはスキップされます。
たとえば、次の動的実行可能ファイル prog は、シンボル foo と bar を参照します。これらのシンボルは、フィルタ filter.so.1 からのリンク編集中に解決されます。prog を実行すると、foo と bar が、フィルタ filter.so.1 からではなく、「フィルティー」 filtee.so.1 から取得されます。
$ cat main.c extern char * bar, * foo(); void main() { (void) printf("foo is %s: bar is %s\n", foo(), bar); } $ cc -o prog main.c -R. filter.so.1 $ prog foo is defined in filtee: bar is defined in filtee |
次の例では、共有オブジェクト filter.so.2 は、インタフェースの 1 つである foo を フィルティー filtee.so.1 上のフィルタとして定義します。
foo() にはソースコードが提供されていないので、mapfile のキーワードである FUNCTION を使用して、foo のシンボルテーブルエントリが作成されることを確認します。
$ cat filter.c char * bar = "defined in filter"; $ cat mapfile { global: foo = FUNCTION FILTER filtee.so.1; }; $ cc -o filter.so.2 -G -K pic -h filter.so.2 -M mapfile -R. filter.c $ elfdump -d filter.so.2 | egrep "SONAME|FILTER" [2] SONAME 0xd8 filter.so.2 [3] SUNW_FILTER 0xfb filtee.so.1 $ elfdump -y filter.so.2 | egrep "foo|bar" [1] F [3] filtee.so.1 foo [10] D <self> bar |
実行時にフィルタのシンボル foo を参照すると、必ず「フィルティー」filtee.so.1 がさらに読み込まれます。実行時リンカーは、「フィルティー」を使用して、filter.so.2 が定義したシンボル foo だけを解決します。シンボル bar への参照は、 filter.so.2 からのシンボルを常に使用し、このシンボルに対して「フィルティー」処理は定義されません。
たとえば、次の動的実行可能ファイル prog は、フィルタ filter.so.2 からのリンク編集中に解決されるシンボル foo と bar を参照します。prog の実行により、foo が「フィルティー」filtee.so.1 から取得され、bar がフィルタ filter.so.2 から取得されます。
$ cc -o prog main.c -R. filter.so.2 $ prog foo is defined in filtee: bar is defined in filter |
これらの例では、「フィルティー」filtee.so.1 がフィルタに一意に関連付けられています。このため、prog を実行した結果読み込まれる可能性があるほかのオブジェクトからのシンボル参照を満たすために、「フィルティー」を使用することができません。
標準フィルタは、既存の共有オブジェクトのサブセットインタフェースを定義するための便利なメカニズムを提供します。標準フィルタは、多数の既存の共有オブジェクトに及ぶインタフェースグループを作成します。標準フィルタはまた、インタフェースをその実装にリダイレクトする手段も提供します。一部の標準フィルタは、Solaris OS で使用されます。
/usr/lib/libsys.so.1 フィルタは、標準 C ライブラリ /usr/lib/libc.so.1 のサブセットを提供します。このサブセットは、ABI に準拠するアプリケーションがインポートしなければならない C ライブラリ内の ABI に準拠する関数とデータ項目を表します。
/lib/libxnet.so.1 フィルタは、複数の「フィルティー」を使用します。このライブラリは、/lib/libsocket.so.1、 /lib/libnsl.so.1、および /lib/libc.so.1 から、ソケットと XTI インタフェースを提供します。
libc.so.1 は、実行時リンカーへのインタフェースフィルタを定義します。これらのインタフェースは、libc.so.1 のコンパイル環境で参照されるシンボルと ld.so.1(1) の実行時環境内で作り出される実際の実装結合間の抽象化を提供します。
libnsl.so.1 は、標準フィルタ gethostname(3C) を libc.so.1 に対して定義します。以前は、libnsl.so.1 も libc.so.1 もこのシンボルの同じ実装を提供していました。libnsl.so.1 をフィルタとして設定することで、gethostname() の実装は 1 つだけ必要となります。libnsl.so.1 は継続して gethostname() をエクスポートするため、このライブラリインタフェースも以前のリリースと互換性があります。
標準フィルタ内のコードは実行時に参照されることはないため、フィルタとして定義された関数に内容を追加しても意味がありません。どのようなフィルタコードでも再配置を必要とする場合があり、実行時にそのフィルタを処理すると不要なオーバーヘッドが生じます。関数は空のルーチンとして定義するか、直接 mapfile から定義してください。「mapfile を使用した追加シンボルの定義」を参照してください。
フィルタ内にデータシンボルを生成するときは、常にデータをセクションに関連付けてください。この関連付けは、再配置可能なオブジェクトファイル内にシンボルを定義することで行うことができます。この関連付けは、mapfile 内でシンボルを size 宣言あり、 value 宣言なしで定義しても行うことができます。「mapfile を使用した追加シンボルの定義」を参照してください。このようにデータを定義することで、動的実行可能ファイルからの参照が正しく確立されます。
リンカーによって実行される、より複雑なシンボル解決の中には、シンボルサイズを含むシンボルの属性に関する知識を必要とするものがあります。このため、フィルタ内のシンボルの属性が「フィルティー」内のシンボルの属性と一致するようにシンボルを生成する必要があります。属性の一貫性を維持することで、リンク編集処理では、実行時に使用されるシンボル定義と互換性のある方法でフィルタが解析されます。「シンボル解決」を参照してください。
リンカーは、処理される最初の再配置可能ファイルの ELF クラスを使用して、作成するオブジェクトのクラスを管理します。64 ビットフィルタを mapfile だけから作成するには、リンカーの -64 オプションを使用します。