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

限制Linux静态库中的符号

如何解决《限制Linux静态库中的符号》经验,为你挑选了3个好方法。

我正在寻找限制导出到Linux静态库(存档)的C符号数量的方法.我想将这些仅限于那些属于该库官方API的符号.我已经使用'static'将大多数函数声明为static,但是这会将它们限制为文件范围.我正在寻找一种限制图书馆范围的方法.

我可以使用Ulrich Drepper的" 如何编写共享库"中的技术为共享库执行此操作,但我无法将这些技术应用于静态存档.在他早期的图书馆设计良好实践论文中,他写道:

唯一的可能性是使用'ld -r'将需要某些内部资源的所有目标文件合并为一个,然后限制由此组合目标文件导出的符号.GNU链接器可以选择执行此操作.

谁能帮助我发现这些选项可能是什么?我使用'strip -w -K prefix_*'取得了一些成功,但这感觉很野蛮.理想情况下,我想要一个适用于GCC 3和4的解决方案.

谢谢!



1> 小智..:

对于使用GCC 3.x或4.x编译的代码,静态库无法执行您想要的操作.

如果您可以使用共享对象(库),GNU链接器将通过称为版本脚本的功能来执行您所需的操作.这通常用于提供特定于版本的入口点,但是退化情况只是区分公共和私有符号而没有任何版本控制.使用ld的--version-script =命令行选项指定版本脚本.

版本脚本的内容使得入口指向foo和bar为public并隐藏所有其他接口:

{ global: foo; bar; local: *; };

请参阅ld doc:http://sourceware.org/binutils/docs/ld/VERSION.html#VERSION

我是共享库的主要倡导者,这种限制全局变量可见性的能力是他们的伟大优点之一.

提供共享对象的更多优点但是为Solaris编写的文档(由Greg Nakhimovsky撰写的快乐记忆)位于http://developers.sun.com/solaris/articles/linker_mapfiles.html

我希望这有帮助.



2> Employed Rus..:

我不相信GNU ld有任何这样的选择; 乌尔里希一定意味objcopy,那里有很多这样的选项:--localize-hidden,--localize-symbol=symbolname,--localize-symbols=filename.

--localize-hidden特别允许一个具有非常精细地控制哪些符号被暴露.考虑:

int foo() { return 42; }
int __attribute__((visibility("hidden"))) bar() { return 24; }

gcc -c foo.c
nm foo.o
000000000000000b T bar
0000000000000000 T foo

objcopy --localize-hidden foo.o bar.o
nm bar.o
000000000000000b t bar
0000000000000000 T foo

因此bar()不再从对象中导出(即使它仍然存在并可用于调试).你也可以bar()一起删除所有objcopy --strip-unneeded.



3> Jon Chesterf..:

这个答案的优点将取决于您使用静态库的原因.如果允许链接器稍后删除未使用的对象,那么我几乎无法添加.如果它是为了组织的目的 - 最小化必须传递给链接应用程序的对象的数量 - 这种对Employed Russian的答案的扩展可能是有用的.

在编译时,可以使用以下命令设置编译单元中所有符号的可见性:

-fvisibility=hidden
-fvisibility=default

这意味着可以编译具有默认可见性的单个文件"interface.c"和具有隐藏可见性的大量实现文件,而无需注释源.然后,可重定位链接将生成单个目标文件,其中非api函数被"隐藏":

ld -r interface.o implementation0.o implementation1.o -o relocatable.o

现在可以对组合的目标文件进行objcopy:

objcopy --localize-hidden relocatable.o mylibrary.o

因此,我们有一个目标文件"library"或"module",它只公开预期的API.


上述策略与链接时间优化适度地相互作用.使用-flto编译并通过编译器将-r传递给链接器来执行可重定位链接:

gcc -fuse-linker-plugin -flto -nostdlib -Wl,-r {objects} -o relocatable.o

使用objcopy像以前一样本地化隐藏的符号,然后最后一次调用链接器来剥离本地符号以及它可以在post-lto对象中找到的任何其他死代码.遗憾的是,relocatable.o不太可能保留任何与lto相关的信息:

gcc -nostdlib -Wl,-r,--discard-all relocatable.o mylibrary.o

lto的当前实现在可重定位链接阶段期间似乎是活动的.使用lto,隐藏的=>本地符号被最终的可重定位链接剥离.没有lto,hidden => local符号在最终的可重定位链接中幸存下来.

lto的未来实现似乎可能通过可重定位链接阶段保留所需的元数据,但是目前可重定位链接的结果似乎是一个普通的旧目标文件.

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