某些平台要求您向链接器提供共享库的外部符号列表.但是,在大多数不需要的unixish系统上:默认情况下,所有非静态符号都可用.
我的理解是,GNU工具链可以选择性地将可见性限制为显式声明的符号.如何使用GNU ld实现这一目标?
GNU ld
可以在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仍然会为稍后由链接描述文件导出的函数产生额外的间接.因此,使用visibility属性将生成比链接器脚本更好的代码.