限制Linux静态库中的符号

我正在寻找方法来限制导出到Linux静态库(存档)的C符号的数量。 我只想限制这些符号是图书馆官方API的一部分。 我已经使用“静态”来声明大多数函数是静态的,但是这限制了它们的文件范围。 我正在寻找一种方法来限制图书馆的范围。

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

唯一的可能是将所有需要一定内部资源的目标文件合并到一个使用'ld -r'的文件中,然后限制这个合并目标文件导出的符号。 GNU链接器有选项可以做到这一点。

谁能帮我发现这些选项可能是什么? 我用“strip -w -K prefix_ *”取得了一些成功,但是这感觉很糟糕。 理想情况下,我想要一个解决scheme,将与GCC 3和4一起工作。

谢谢!

Solutions Collecting From Web of "限制Linux静态库中的符号"

对于使用GCC 3.x或4.x编译的代码,静态库不能做你想要的。

如果您可以使用共享对象(库),那么GNU链接器就会使用称为版本脚本的功能来完成您所需要的功能。 这通常用于提供特定于版本的入口点,但简并案例只是区分公共和私有符号而没有任何版本。 版本脚本通过–version-script =命令行选项指定给ld。

使入口点foo和bar公开并隐藏所有其他接口的版本脚本的内容:

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

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

我是共享库的主要倡导者,而这种限制全局的可见性的能力是他们的伟大美德。

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

我希望这有帮助。

我不相信GNU有这样的选择; Ulrich一定是指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()不再从对象中导出(即使它仍然存在并且可用于调试)。 你也可以用objcopy --strip-unneededbar()全部删除。

这个答案的优点将取决于你为什么使用静态库。 如果它允许链接器稍后放弃未使用的对象,那么我几乎没有添加。 如果是为了组织的目的 – 尽量减少必须传递的链接应用程序的对象的数量 – 这个扩展的就业俄语的答案可能是有用的。

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

 -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 

因此,我们有一个单一的对象文件“库”或“模块”,只暴露了预期的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,隐藏的=>本地符号在最终的可重定位链接中存活下来。

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

我这样做的方法是用INTERNAL标记所有不能输出的内容,包括保护所有的.h文件,使用-DINTERNAL =编译开发版本,编译发布版本包含所有其他库.c文件与-DINTERNAL =静态。