限制 Linux 静态库中的符号

2024-11-14 08:30:00
admin
原创
20
摘要:问题描述:我正在寻找方法来限制导出到 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。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用