Go to main content
Oracle® Solaris 11.3 リンカーとライブラリガイド

印刷ビューの終了

更新: 2015 年 10 月
 
 

機能要件の指定

システム機能は、実行中のシステムを記述する機能です。プラットフォーム名およびマシンハードウェア名は、それぞれ –i オプションと –m オプションを使用すると、uname(1)で表示できます。システムのハードウェア機能は、–v オプションを使用してisainfo(1)で表示できます。実行時にオブジェクトのプラットフォーム名、マシンハードウェア名、およびハードウェア機能要件がシステム機能と比較され、オブジェクトをロードできるかどうか、またはオブジェクト内のシンボルを使用できるかどうかが判定されます。

オブジェクト機能は、オブジェクトに関連する機能です。これらの機能はオブジェクト全体の要件を定義します。プラットフォーム、マシン、およびハードウェア機能は、実行時にオブジェクトをロードできるかどうかを制御します。あるオブジェクトが、システムで満たすことができない機能を要求している場合、そのオブジェクトは実行時に読み込めません。機能を使用すると任意のオブジェクトから複数のインスタンスを作成でき、各インスタンスはオブジェクト要件に一致するシステムに最適化されます。実行時リンカーは、オブジェクトの機能要件をシステムが提供する機能と比較することで、このようなオブジェクトインスタンスファミリの中から最適なインスタンスを透過的に選択します。

シンボル機能は、オブジェクト内の各関数または初期化されたデータ項目に関連する機能です。プラットフォーム、マシン、およびハードウェア機能は、オブジェクト内の 1 つまたは複数のシンボルの要件を定義し、実行時にシンボルを使用できるかどうかを制御します。シンボル機能によって、1 つの関数の複数のインスタンスが 1 つのオブジェクト内に存在できます。関数の各インスタンスは、別々の機能を持つシステムに対して最適化できます。また、1 つの初期化されたデータ項目の複数のインスタンスも 1 つのオブジェクト内に存在できます。データの各インスタンスはシステム固有のデータを定義できます。シンボルのインスタンスが、システムによって満たすことができない機能を要求している場合、そのシンボルインスタンスは実行時に使用できません。代わりに、同じシンボル名の代替インスタンスを使用する必要があります。シンボル機能では、単一のオブジェクトをさまざまな機能のシステムで使用できるようにオブジェクトを構築できます。機能ファミリは、機能に対応できるシステム向けの最適化されたインスタンスと、機能が比較的低いほかのシステム向けのより汎用的なインスタンスを提供できます。初期化されたデータ項目のファミリはシステム固有データを提供できます。実行時リンカーは、シンボルの機能要件をシステムが提供する機能と比較することで、このようなシンボルインスタンスファミリの中から最適なインスタンスを透過的に選択します。

オブジェクトとシンボルの機能は、現在動作中のシステムに対して最適なオブジェクト、およびオブジェクト内の最適なシンボルを選択できます。オブジェクトとシンボルの機能はオプションであり、互いに独立しています。ただし、シンボル機能を定義しているオブジェクトがオブジェクト機能を定義してもかまいません。この場合、機能シンボルファミリには、オブジェクト機能を満たすシンボルの 1 つのインスタンスが伴われることになります。オブジェクトの機能が存在しない場合、機能シンボルファミリには、機能を要求しないシンボルの 1 つのインスタンスが伴われることになります。指定されたシステムに適合できる機能インスタンスがない場合、このシンボルインスタンスによってデフォルト実装が提供されます。

次の x86 の例は、foo.o のオブジェクト機能を示します。これらの機能はオブジェクト全体に適用されます。この例には、シンボル機能がありません。

$ elfdump -H foo.o

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]

次の x86 の例は、bar.o のシンボル機能を示します。これらの機能は個々の関数 foo() および bar() に適用されます。各シンボルのインスタンスは 2 つ存在し、それぞれのインスタンスは別々の機能セットに割り当てられています。この例には、オブジェクト機能がありません。

$ elfdump -H bar.o

Capabilities Section:  .SUNW_cap

 Symbol Capabilities:
     index  tag               value
       [1]  CA_SUNW_HW_1      0x40  [ MMX ]

  Symbols:
     index    value     size  type bind oth ver shndx    name
      [25]        0     0x21  FUNC LOCL  D    0 .text    foo%mmx
      [26]     0x24     0x1e  FUNC LOCL  D    0 .text    bar%mmx

 Symbol Capabilities:
     index  tag               value
       [3]  CA_SUNW_HW_1      0x800  [ SSE ]

  Symbols:
     index    value     size  type bind oth ver shndx    name
      [33]     0x44     0x21  FUNC LOCL  D    0 .text    foo%sse
      [34]     0x68     0x1e  FUNC LOCL  D    0 .text    bar%sse

注 -  この例では、機能シンボルは、機能識別子を汎用のシンボル名に追加する命名規則に従っています。リンカーはこの規則に従ってオブジェクト機能をシンボル機能に変換できます。あとで説明するオブジェクト機能のシンボル機能への変換を参照してください。

機能定義には、オブジェクトの要件、またはオブジェクト内の各シンボルの要件を特定できる多くの組み合わせが用意されています。


注 -  プラットフォーム名とマシンハードウェア名は、ごくわずかなバリエーションに集約されています。これらの機能名は特定のマシンを対象とするために作成されたもので、もっとも高い優先順位を持ちますが、現在その有用性は限られています。コードを特定のプラットフォームまたはマシン用に限定することは、場合によって有効ですが、ハードウェア機能ファミリを作成する方が柔軟性を高めることができるため、この方法を推奨します。ハードウェア機能ファミリは、コードを幅広いシステムで実行できるように最適化できます。

次のセクションでは、機能の定義方法とリンカーによる使用方法について説明します。

プラットフォームおよびマシン機能の指定

オブジェクトのプラットフォームまたはマシン機能では、オブジェクトまたはオブジェクト内の特定のシンボルが実行できるシステムのプラットフォーム名またはマシンハードウェア名を指定します。複数のプラットフォームまたはマシン機能を定義できます。これらの指定はもっとも具体的であり、ほかの機能タイプに優先します。これらの指定は特殊なシステムライブラリで使用できますが、通常はハードウェア機能の方がより柔軟に機能インスタンスを作成する手段を提供します。

システムのプラットフォーム名は、ユーティリティーuname(1)–i オプションを付けて実行すると表示できます。プラットフォーム機能要件は次の mapfile 構文を使用すると定義できます。

    $mapfile_version 2
        CAPABILITY {
                PLATFORM  = platform_name...;
                PLATFORM += platform_name...;
                PLATFORM -= platform_name...;
        };

システムのマシンハードウェア名は、ユーティリティーuname(1)–m オプションを付けて実行すると表示できます。マシン機能要件は次の mapfile 構文を使用すると定義できます。

    $mapfile_version 2
        CAPABILITY {
                MACHINE  = machine_name...;
                MACHINE += machine_name...;
                MACHINE -= machine_name...;
        };

PLATFORM または MACHINE 属性は、スペースで区切られた 1 つまたは複数のプラットフォーム名またはマシン名で修飾されます。「+=」形式の代入を使用すると、入力オブジェクトで指定されたプラットフォーム機能またはマシン機能に追加できます。「=」形式はこれらをオーバーライドします。「-=」形式の代入を使用すると、出力オブジェクトからプラットフォーム機能またはマシン機能を削除できます。

次の SPARC の例では、オブジェクト foo.so.1sun4v マシンハードウェア名に固有であることを指定します。

$ cat mapfile
$mapfile_version 2
CAPABILITY {
        MACHINE = sun4v;
};
$ cc -o foo.so.1 -G -K pic -Mmapfile foo.c -lc
$ elfdump -H foo.so.1

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_MACH      sun4v

再配置可能オブジェクトはプラットフォーム機能またはマシン機能を定義できます。これらの機能がまとめられて、作成中のオブジェクトの最終的な機能要件が定義されます。

オブジェクトのプラットフォーム機能またはマシン機能は、「=」形式の代入を使用すると mapfile から明示的に制御でき、入力の再配置可能オブジェクトから指定される可能性のあるプラットフォーム機能またはマシン機能をオーバーライドできます。「=」形式の代入を使用して空の PLATFORM または MACHINE 属性を指定すると、作成中のオブジェクトからプラットフォームまたはマシンのすべての機能要件が削除されます。

動的オブジェクトで定義されたプラットフォームまたはマシンの機能要件は、システムのプラットフォーム名またはマシン名に照らして、実行時リンカーによって検証されます。オブジェクトが使用されるのは、オブジェクトに記録されたプラットフォーム名またはマシン名の 1 つがシステムのプラットフォーム名またはマシン名に一致した場合だけです。

ハードウェア機能の指定

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

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

    $mapfile_version 2
        CAPABILITY {
                HW  = hwcap_flag...;
                HW += hwcap_flag...;
                HW -= hwcap_flag...;
        };

CAPABILITY 指令に対する HW 属性は、ハードウェア機能のシンボル表現である 1 つまたは複数のトークンで修飾されます。「+=」形式の代入を使用すると、入力オブジェクトで指定されたハードウェア機能に追加できます。「=」形式はオーバーライドします。「-=」形式の代入を使用すると、出力オブジェクトからハードウェア機能を削除できます。

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
$mapfile_version 2
CAPABILITY {
        HW += SSE MMX;
};
$ cc -o foo.so.1 -G -K pic -Mmapfile foo.c -lc
$ elfdump -H foo.so.1

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]

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

オブジェクトのハードウェア機能要件は、「=」形式の代入を使用すると mapfile から明示的に制御でき、入力の再配置可能オブジェクトから指定される可能性のあるハードウェア機能をオーバーライドできます。「=」形式の代入を使用して空の HW 属性を指定すると、作成中のオブジェクトからハードウェアのすべての機能要件が削除されます。

次の例では、入力の再配置可能オブジェクト foo.o で定義されたハードウェア機能のデータが出力ファイル bar.o に含まれないように隠されています。

$ elfdump -H foo.o

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]
$ cat mapfile
$mapfile_version 2
CAPABILITY {
        HW = ;
};
$ ld -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 ]
        ....

別々のハードウェア機能を利用する動的オブジェクトの複数のインスタンスは、フィルタを使用することによって、柔軟な実行時環境を提供できます。機能固有の共有オブジェクトを参照してください。

ハードウェア機能は、1 つのオブジェクト内の個々の関数の機能を指定するためにも使用できます。この場合、実行時リンカーは現在のシステム機能に基づいて使用する最適な関数を選択できます。シンボル機能関数ファミリの作成を参照してください。

ソフトウェア機能の指定

オブジェクトのソフトウェア機能は、プロセスのデバッグまたはモニタリングにとって重要なことがあるソフトウェアの特徴を特定します。ソフトウェア機能はプロセスの実行にも影響を与えることができます。現在のところ、オブジェクトによるフレームポインタの使用、およびプロセスアドレス空間の制限に関連したソフトウェア機能のみが存在します。

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

64 ビットのオブジェクトは、実行時に 32 ビットのアドレス空間内で実行しなければならないことを指定できます。

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

#define  SF1_SUNW_FPKNWN    0x001
#define  SF1_SUNW_FPUSED    0x002
#define  SF1_SUNW_ADDR32    0x004

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

    $mapfile_version 2
        CAPABILITY {
                SF  = sfcap_flags...;
                SF += sfcap_flags...;
                SF -= sfcap_flags...;
        };

CAPABILITY 指令に対する SF 属性は、トークン FPKNWN FPUSED、および ADDR32 のいずれにも割り当てることができます。

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

オブジェクトのソフトウェア機能要件は、「=」形式の代入を使用すると mapfile から明示的に制御でき、入力の再配置可能オブジェクトから指定される可能性のあるソフトウェア機能をオーバーライドできます。「=」形式の代入を使用して空の HW 属性を指定すると、作成中のオブジェクトからソフトウェアのすべての機能要件が削除されます。

次の例では、入力の再配置可能オブジェクト foo.o で定義されたソフトウェア機能のデータが出力ファイル bar.o に含まれないように隠されています。

$ elfdump -H foo.o

Object Capabilities:
    index  tag               value
      [0]  CA_SUNW_SF_1      0x3  [ SF1_SUNW_FPKNWN  SF1_SUNW_FPUSED ]
$ cat mapfile
$mapfile_version 2
CAPABILITY {
        SF = ;
};
$ ld -o bar.o -r -Mmapfile foo.o
$ elfdump -H bar.o
$ 

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

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

表 1  CA_SUNW_SF_1 フレームポインタフラグ組み合わせ状態テーブル
入力ファイル 1
入力ファイル 2
結果
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
SF1_SUNW_FPKNWN
SF1_SUNW_FPKNWN
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
<unknown>
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
SF1_SUNW_FPKNWN
<unknown>
SF1_SUNW_FPKNWN
<unknown>
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
SF1_SUNW_FPKNWN SF1_SUNW_FPUSED
<unknown>
SF1_SUNW_FPKNWN
SF1_SUNW_FPKNWN
<unknown>
<unknown>
<unknown>

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

ソフトウェア機能アドレス空間制限処理

SF1_SUNW_ADDR32 ソフトウェア機能フラグによって識別される 64 ビットオブジェクトは、32 ビットアドレス空間を必要とする最適化されたコードを含むことができます。この方法で識別される 64 ビットオブジェクトは、SF1_SUNW_ADDR32 フラグで識別されるかどうかにかかわらず、他の 64 ビットオブジェクトと相互運用できます。64 ビット入力再配置可能オブジェクト内で SF1_SUNW_ADDR32 フラグが現れると、リンカーによって作成される出力ファイル用に作成される CA_SUNW_SF_1 値に反映されます。

64 ビット実行可能ファイル内に SF1_SUNW_ADDR32 フラグが存在すると、関連付けられたプロセスは下位 32 ビットアドレス空間に確実に制限されます。この制限付きアドレス空間には、プロセススタックと、すべてのプロセス依存関係が含まれます。そのようなプロセスの内部では、すべてのオブジェクトは SF1_SUNW_ADDR32 フラグで識別されるかどうかにかかわらず、制限付き 32 ビットアドレス空間内に読み込まれます。

64 ビット共有オブジェクトは SF1_SUNW_ADDR32 フラグを含むことができます。ただし、制限付きアドレス空間要件は、SF1_SUNW_ADDR32 フラグを含む 64 ビット実行可能ファイルによってのみ設定できます。したがって、64 ビットの SF1_SUNW_ADDR32 共有オブジェクトは64 ビットの SF1_SUNW_ADDR32 実行可能ファイルに依存する必要があります。

制限付きでない 64 ビット実行可能ファイルを構築するとき、64 ビットの SF1_SUNW_ADDR32 共有オブジェクトがリンカーによって検出されると、警告が発生します。

$ cc -m64 -o main main.c -lfoo
ld: warning: file libfoo.so: section .SUNW_cap: software capability ADDR32: \
    requires executable be built with ADDR32 capability

制限付きでない 64 ビットの実行可能ファイルから作成されたプロセスによって 64 ビットの SF1_SUNW_ADDR32 共有オブジェクトが実行時に検出されると、致命的エラーが発生します。

$ ldd main
    libfoo.so =>     ./libfoo.so  - software capability unsupported: 0x4  [ ADDR32 ]
    ....
$ main
ld.so.1: main: fatal: ./libfoo.so: software capability unsupported: 0x4  [ ADDR32 ]

実行可能ファイルには、mapfile を使用して SF1_SUNW_ADDR32 をシードできます。

$ cat mapfile
$mapfile_version 2
CAPABILITY {
        SF += ADDR32;
};
$ cc -m64 -o main main.c -Mmapfile -lfoo
$ elfdump -H main

Object Capabilities:
    index  tag               value
      [0]  CA_SUNW_SF_1      0x4  [ SF1_SUNW_ADDR32 ]