リンカーとライブラリ

補助フィルタの生成

補助フィルタを生成するには、まずフィルタ処理を適用する「フィルティー」を定義する必要があります。次の例では、シンボル foo を提供する「フィルティー」filtee.so.1 を構築します。


$ cat filtee.c
char * foo()
{
        return("defined in filtee");
}
$ cc -o filtee.so.1 -G -K pic filtee.c

補助フィルタ処理は、2 つの方法のいずれかで提供できます。共有オブジェクトによって提供されるすべてのインタフェースを補助フィルタとして宣言するには、リンカーの -f フラグを使用します。共有オブジェクトの個々のインタフェースを補助フィルタとして宣言するには、リンカーの mapfile と AUXILIARY キーワードを使用します。

次の例では、共有オブジェクト filter.so.1 が補助フィルタとして定義されています。filter.so.1 はシンボル foo と bar を提供し、それ自体が「フィルティー」filtee.so.1 の補助フィルタです。この例では、コンパイラドライバが -f オプションを解釈しないように、環境変数 LD_OPTIONS が使用されています。


$ cat filter.c
char * bar = "defined in filter";

char * foo()
{
        return ("defined in filter");
}
$ 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|AUXILIARY"
    [2]  SONAME           0xee     filter.so.1
    [3]  AUXILIARY        0xfb     filtee.so.1

動的実行可能ファイルまたは共有オブジェクトを作成する場合、リンカーは補助フィルタ filter.so.1 を依存関係として参照できます。リンカーは、フィルタのシンボルテーブルの情報を使用してシンボル解決を行います。しかし、実行時にフィルタのシンボルを参照すると、「フィルティー」filtee.so.1 が検索されます。この「フィルティー」が見つかると、実行時リンカーは、この「フィルティー」を使用して、filter.so.1 によって定義されたすべてのシンボルを解決します。この「フィルティー」が見つからないか、あるいは「フィルティー」内にフィルタからのシンボルが見つからない場合は、フィルタ内の元のシンボルが使用されます。

たとえば、次の動的実行可能ファイル prog は、シンボル foo と bar を参照します。これらのシンボルは、フィルタ filter.so.1 からのリンク編集中に解決されます。prog を実行すると、foo が、フィルタ filter.so.1 からではなく、「フィルティー」 filtee.so.1 から取得されます。しかし、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 filter

次の例では、共有オブジェクト filter.so.2 は、インタフェース foo をフィルティーfiltee.so.1 上の補助フィルタとして定義します。


$ cat filter.c
char * bar = "defined in filter";

char * foo()
{
        return ("defined in filter");
}
$ cat mapfile
{
	global:
		foo = AUXILIARY 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|AUXILIARY"
    [2]  SONAME           0xd8     filter.so.2
    [3]  SUNW_AUXILIARY   0xfb     filtee.so.1
$ elfdump -y filter.so.2 | egrep "foo|bar"
    [1]  A    [3] filtee.so.1      foo
   [10]  D        <self>           bar

実行時にフィルタのシンボル foo を参照すると、必ず「フィルティー」filtee.so.1 が検索されます。「フィルティー」が見つかると、「フィルティー」が読み込まれます。「フィルティー」は filter.so.2 によって定義されたシンボル foo の解決に使用されます。「フィルティー」が検索されなかった場合、filter.so.2 によって定義されたシンボル foo が使用されます。シンボル bar への参照は、 filter.so.2 からのシンボルを常に使用し、このシンボルに対して「フィルティー」処理は定義されません。

たとえば、次の動的実行可能ファイル prog は、フィルタ filter.so.2 からのリンク編集中に解決されるシンボル foo と bar を参照します。「フィルティー」 filtee.so.1 が存在する場合、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 を実行すると、foo と bar がフィルタ filter.so.2 から取得されます。


$ prog
foo is defined in filter: bar is defined in filter

これらの例では、「フィルティー」filtee.so.1 がフィルタに一意に関連付けられています。このため、prog を実行した結果読み込まれる可能性があるほかのオブジェクトからのシンボル参照を満たすために、「フィルティー」を使用することができません。

補助フィルタは、既存の共有オブジェクトの代替インタフェースを定義するメカニズムとなります。このメカニズムは、ハードウェア機能での最適な機能およびプラットフォーム固有の共有オブジェクトを提供するために Solaris OS で使用されます。例は、「ハードウェア機能固有の共有オブジェクト」、「命令セット固有の共有オブジェクト」、および 「システム固有の共有オブジェクト」を参照してください。


注 –

環境変数 LD_NOAUXFLTR を設定すれば、実行時リンカーの補助フィルタ処理を無効にすることができます。補助フィルタはプラットフォーム固有の最適化に使用されることが多いので、「フィルティー」の使用およびそれらの性能インパクトを評価する場合にこのオプションが便利です。