限制 Linux 静态库中的符号

2024-11-14 08:30:00
admin
原创
24
摘要:问题描述:我正在寻找方法来限制导出到 Linux 静态库(存档)的 C 符号数量。我想将这些符号限制为仅属于库的官方 API 的那些符号。我已经使用“static”将大多数函数声明为静态,但这将它们限制在文件范围内。我正在寻找一种方法来将范围限制在库内。我可以使用 Ulrich Drepper 的《如何编写共...

问题描述:

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

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

唯一的办法是使用“ld -r”将所有需要特定内部资源的目标文件合并为一个,然后限制此合并的目标文件导出的符号。GNU 链接器有选项可以执行此操作。

有人能帮我找出这些选项吗?我使用“strip -w -K prefix_*”取得了一些成功,但这感觉很粗暴。理想情况下,我想要一个可以同时适用于 GCC 3 和 4 的解决方案。

谢谢!


解决方案 1:

我不相信 GNU ld 有任何这样的选项;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()不再从对象中导出(即使它仍然存在并且可用于调试)。您也可以将bar()和 一起删除objcopy --strip-unneeded

解决方案 2:

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

如果您可以使用共享对象(库),GNU 链接器会使用称为版本脚本的功能满足您的需求。这通常用于提供特定于版本的入口点,但退化情况仅区分公共和私有符号,而不进行任何版本控制。版本脚本是使用 ld 的 --version-script= 命令行选项指定的。

版本脚本的内容使入口点 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

我希望这会有所帮助。

解决方案 3:

这个答案的优点取决于你使用静态库的原因。如果是为了让链接器稍后删除未使用的对象,那么我没什么可补充的。如果是为了组织的目的——尽量减少必须传递以链接应用程序的对象数量——那么 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

因此,我们有一个仅公开预期 API 的单一目标文件“库”或“模块”。


上述策略与链接时间优化的相互作用相当好。使用 -flto 进行编译,并通过编译器将 -r 传递给链接器来执行可重定位链接:

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

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

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

lto 的当前实现似乎在可重定位链接阶段处于活动状态。启用 lto 后,隐藏=>本地符号会被最终的可重定位链接剥离。未启用 lto 时,隐藏=>本地符号会在最终的可重定位链接中保留下来。

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

解决方案 4:

这是对 EmployedRussian 和 JonChesterfield 的答案的改进,如果您同时生成动态库和静态库,这可能会有所帮助。

从隐藏 DSO(库的动态版本)中的符号的标准机制开始。使用 编译所有文件-fvisibility=hidden。在定义 API 的头文件中,更改要公开的类和函数的声明:

   #define DLL_PUBLIC __attribute__ ((visibility ("default")))
   extern DLL_PUBLIC int my_api_func(int);

详情请参阅此处。这适用于 C 和 C++。这对于 DSO 来说已经足够了,但您需要为静态库添加以下构建步骤:

ld -r obj1.o obj2.o ... objn.o -o static1.o
objcopy --localize-hidden static1.o static2.o
ar -rcs mylib.a static2.o

ar步骤是可选的 - 您可以直接链接到static2.o

解决方案 5:

我的做法是将所有不导出的内容标记为 INTERNAL,包括所有 .h 文件,使用 -DINTERNAL= 编译开发版本,并使用包含所有其他库 .c 文件的单个 .c 文件编译发布版本,并使用 -DINTERNAL=static。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   609  
  在现代项目管理中,资源的有效利用是确保项目成功的关键因素之一。随着技术的不断进步,越来越多的工具和软件被开发出来,以帮助项目经理和团队更高效地管理资源。本文将介绍10款工具,这些工具可以帮助项目团队提升资源利用效率,从而实现项目目标。禅道项目管理软件禅道项目管理软件是一款开源的项目管理工具,广泛应用于软件开发和其他行业...
项目管理系统   3  
  在项目管理领域,软件工具的不断升级和创新是推动效率和协作的关键。2024年,众多项目管理软件将迎来一系列令人期待的升级功能,这些新特性不仅将提升团队的工作效率,还将增强用户体验和数据分析能力。本文将详细介绍10款项目管理软件的最新升级功能,帮助项目经理和团队成员更好地规划和执行项目。禅道项目管理软件禅道项目管理软件一直...
开源项目管理工具   2  
  信创国产系统的10个关键厂商及其技术生态随着全球信息技术格局的不断演变,信创(信息技术应用创新)产业作为国产化替代的重要阶段,正逐步成为推动我国信息技术自主可控、安全可靠的核心力量。信创产业不仅关乎国家信息安全,也是数字经济高质量发展的关键支撑。本文将深入探讨信创国产系统中的10个关键厂商及其技术生态,分析它们在信创浪...
项目管理流程   0  
  在探讨项目管理的广阔领域中,成功并非偶然,而是精心策划、高效执行与持续优化的结果。项目管理的成功之道,可以从明确的目标设定与规划、高效的团队协作与沟通、以及灵活的风险管理与适应变化这三个核心方面进行深入解析。每个方面都是项目成功的基石,它们相互交织,共同支撑起项目的顺利推进与最终成就。明确的目标设定与规划项目管理的首要...
建筑工程项目管理规范   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用