raf*_*afl 45 linker gnu shared-libraries linker-scripts
某些平台要求您向链接器提供共享库的外部符号列表.但是,在大多数不需要的unixish系统上:默认情况下,所有非静态符号都可用.
我的理解是,GNU工具链可以选择性地将可见性限制为显式声明的符号.如何使用GNU ld实现这一目标?
Emp*_*ian 67
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 '
Run Code Online (Sandbox Code Playgroud)
默认情况下,导出所有符号:
0000000000000718 T _fini
00000000000005b8 T _init
00000000000006b7 T bar
00000000000006c9 T baz
00000000000006ac T foo
Run Code Online (Sandbox Code Playgroud)
假设您只想导出bar()和baz().创建"版本脚本" libfoo.version:
FOO {
global: bar; baz; # explicitly list symbols to be exported
local: *; # hide everything else
};
Run Code Online (Sandbox Code Playgroud)
将它传递给链接器:
gcc -fPIC -shared -o libfoo.so foo.c -Wl,--version-script=libfoo.version
Run Code Online (Sandbox Code Playgroud)
观察导出的符号:
nm -D libfoo.so | grep ' T '
00000000000005f7 T bar
0000000000000609 T baz
Run Code Online (Sandbox Code Playgroud)
小智 7
生成用于调用任何导出函数或使用任何导出的全局变量的代码效率低于未导出的函数.涉及额外的间接水平.这适用于可能在编译时导出的任何函数.gcc仍然会为稍后由链接描述文件导出的函数产生额外的间接.因此,使用visibility属性将生成比链接器脚本更好的代码.
似乎有几种方法可以在 GNU/Linux 上管理导出的符号。根据我的阅读,有以下 3 种方法:
-fvisibility=hidden同时__attribute__((visibility("default")))#pragma GCC visibility-Wl,--version-script=<version script file>)我不会在这里举例,因为它们大部分都被其他答案所涵盖,但这里有一些关于不同方法的注释、优缺点:
strip --strip-all --discard-all.我确信还有其他人。
以下是我发现有用的一些参考资料(带有示例):