当前位置:  开发笔记 > 前端 > 正文

链接共享库时限制符号的可见性

如何解决《链接共享库时限制符号的可见性》经验,为你挑选了3个好方法。

某些平台要求您向链接器提供共享库的外部符号列表.但是,在大多数不需要的unixish系统上:默认情况下,所有非静态符号都可用.

我的理解是,GNU工具链可以选择性地将可见性限制为显式声明的符号.如何使用GNU ld实现这一目标?



1> Employed Rus..:

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`。

2> jpalecek..:

我认为最简单的方法是添加-fvisibility=hidden到gcc选项并明确地在代码中公开一些符号公开(by __attribute__((visibility("default")))).请参阅此处的文档.

可能有一种方法可以通过ld链接器脚本实现这一点,但我对此并不了解.


例如,这就是我们在Firefox中所做的事情。
除非没有记录,否则它应该是:__ attribute __((visibility("default")))你应该考虑修改你的答案来反映这一点.此外,您的链接已损坏.

3> 小智..:

生成用于调用任何导出函数或使用任何导出的全局变量的代码效率低于未导出的函数.涉及额外的间接水平.这适用于可能编译时导出的任何函数.gcc仍然会为稍后由链接描述文件导出的函数产生额外的间接.因此,使用visibility属性将生成比链接器脚本更好的代码.

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有