一部のプラットフォームでは、共有ライブラリの外部シンボルのリストをリンカーに提供する必要があります。ただし、ほとんどの unixish システムでは必要ありません。すべての非静的シンボルがデフォルトで使用可能になります。
私の理解では、GNU ツールチェーンはオプションで可視性を明示的に宣言されたシンボルだけに制限できるということです。GNU ldを使用してそれをどのように達成できますか?
一部のプラットフォームでは、共有ライブラリの外部シンボルのリストをリンカーに提供する必要があります。ただし、ほとんどの unixish システムでは必要ありません。すべての非静的シンボルがデフォルトで使用可能になります。
私の理解では、GNU ツールチェーンはオプションで可視性を明示的に宣言されたシンボルだけに制限できるということです。GNU ldを使用してそれをどのように達成できますか?
GNUld
はELFプラットフォームでそれを行うことができます。
リンカバージョンスクリプトを使用してこれを行う方法は次のとおりです。
/* foo.c */
int foo() { return 42; }
int bar() { return foo() + 1; }
int baz() { return bar() - 1; }
gcc -fPIC -shared -o libfoo.so foo.c && nm -D libfoo.so | grep ' T '
デフォルトでは、すべてのシンボルがエクスポートされます。
0000000000000718 T _fini
00000000000005b8 T _init
00000000000006b7 T bar
00000000000006c9 T baz
00000000000006ac T foo
とだけをエクスポートするbar()
としbaz()
ます。「バージョンスクリプト」を作成しますlibfoo.version
。
FOO {
global: bar; baz; # explicitly list symbols to be exported
local: *; # hide everything else
};
それをリンカーに渡します。
gcc -fPIC -shared -o libfoo.so foo.c -Wl,--version-script=libfoo.version
エクスポートされたシンボルを観察します。
nm -D libfoo.so | grep ' T '
00000000000005f7 T bar
0000000000000609 T baz
これを行う最も簡単な方法は、-fvisibility=hidden
gcc オプションに を追加し、明示的にコード内で一部のシンボルを公開することです (by によって__attribute__((visibility("default")))
)。こちらのドキュメントを参照してください。
ld リンカ スクリプトによってそれを実現する方法があるかもしれませんが、私はそれについてあまり知りません。
エクスポートされた関数を呼び出したり、エクスポートされたグローバルを使用したりするために生成されたコードは、エクスポートされていないコードよりも効率的ではありません。余分なレベルの間接化が関係しています。これは、コンパイル時にエクスポートされる可能性のあるすべての関数に適用されます。gcc は、後でリンカー スクリプトによってエクスポートされない関数に対して、追加の間接化を生成します。したがって、可視性属性を使用すると、リンカー スクリプトよりも優れたコードが生成されます。