c - 我可以用我自己的版本替换静态库中的符号吗?
问题描述
使用 gcc/ld,我想使用libfoo.a
,它包含一个符号symbol_foo
(这是一个函数 - 如果重要的话,一个 ISR)。其他功能在libfoo
使用这个功能很明显。我想要做的是编译我自己的二进制文件,使用libfoo.a
,但链接我自己的版本symbol_foo
。
这可能吗?目前,由于符号的多个定义,我得到一个 ld 错误。即它没有在原始静态库中声明为“软链接”或类似的东西。
理想情况下,我希望那里存在类似__attribute__((ld_override))
或其他的东西,但我猜那里没有。有任何想法吗?
解决方案
这取决于图书馆的设计。在您的情况下,答案是“否”,因为该函数在库中没有被隔离。有关库构建的详细说明,请参阅 PJ Plauger The Standard C Library 1992。是的,它相当老,所以标准 C 的版本是 C90,但它所支持的想法仍然有效。
当链接器构建程序时,它正在处理一系列目标文件和库,查找不满足的引用(符号名称)并跟踪定义。在大多数情况下,它main
以未定义的符号开头。
- 当它处理一个目标文件时,它会记录哪些符号被定义满足一个未定义的符号并记住该文件定义的所有名称(如果它发现的符号之一与它已经知道的符号冲突,它会抱怨)。
- 在处理静态库时,它会查找已定义但尚未定义的符号。当它找到这样的符号时,它会链接库中的目标文件,注意哪些符号已定义,哪些仍未定义。
现在,如果目标文件symbol_foo
只包含定义symbol_foo
,那么如果你symbol_foo
在它读取库之前链接了你的,链接器将忽略symbol_foo
库中的;它已经有一个定义,不需要另一个。但是,库中包含的目标文件很可能symbol_foo
还libfoo.a
定义了一些其他符号,而链接器需要这些其他符号,因此它必须链接包含的目标文件symbol_foo
,并抱怨该符号是双重定义的,甚至尽管同一文件中的其他人不是。
Plauger 提倡(静态)库中的每个目标文件都应该定义一个外部符号。这允许库中函数的最大可替代性。我相信可以公平地假设 的设计者libfoo.a
没有做出这个决定,至少 wrt symbol_foo
。
libfoo.a
您可以从(使用临时目录)中提取目标文件并使用nm
; 检查它们的内容。您可以直接在库本身上执行此操作。与适当的选项一起使用,它将向您显示哪些文件定义和引用了哪些其他符号。
请注意,与共享库链接的规则有些不同。还有一些“弱”符号可以改变行为。您通常还可以从多个目标文件(ld -r
通常)创建“可重定位”或“可重新链接”目标文件;这会给你一个更大的目标文件并改变等式。最后,目前,链接描述文件可以控制哪些符号在库外可见。所以,这只不过是对这个主题的一种掩饰。
推荐阅读
- swiftui - SwiftUI 中的 Spring 动画,IOS14 坏了
- bots - Telegram BOT 将电话号码从 Excel 表添加到电报频道
- ios - 自定义可折叠视图
- sql-server - 如何在 T-SQL 中对列的子集执行动态透视
- calculator - 我应该怎么做才能使这个计算器工作?
- flutter - Flutter.framework 大小在发布模式下很大 [400mb]
- database - 一对多上的多对多关系
- node.js - 查询时,Sequelize 模型指向错误的模型
- javascript - 如何防止在嵌套菜单中打开子子菜单
- javascript - OrbitControls 目标更改,使用 Three.js 使鼠标右键移动其他对象