使用 gcc/ld,我想使用 libfoo.a
,它包含一个符号 symbol_foo
(这是一个函数 - 如果重要的话是一个 ISR)。 libfoo
中的其他函数显然使用了这个函数。我想做的是使用 libfoo.a
编译我自己的二进制文件,但链接到我自己的 symbol_foo
版本。
这可能吗?目前,由于符号的多个定义,我收到一个 ld 错误。 IE。它没有在原始静态库中声明为“软链接(soft link)”或类似的东西。
理想情况下,我希望存在诸如 __attribute__((ld_override))
之类的东西,但我猜不存在。有什么想法吗?
最佳答案
这取决于库的设计。在您的情况下,答案是“否”,因为该函数在库中没有被隔离。有关图书馆 build 的精彩阐述,请参阅 P J Plauger The Standard C Library 1992. 是的,它相当古老,所以标准 C 的版本是 C90,但它所支持的思想仍然有效。
链接器在构建程序时,会处理一系列目标文件和库,寻找未满足的引用(符号名称)和跟踪定义。在大多数情况下,它以 undefined symbol main
开头。
- 当它处理一个目标文件时,它会记下定义的哪些符号满足 undefined symbol ,并记住该文件定义的所有名称(如果它找到的符号之一与它已经知道的符号冲突,它会提示).
- 在处理静态库时,它会查找已定义但尚 undefined symbol 。当它找到这样的符号时,它会链接库中的目标文件,并指出哪些符号已定义,哪些仍未定义。
现在,如果包含 symbol_foo
的目标文件只定义了 symbol_foo
,那么如果您在它读取库之前链接了您的 symbol_foo
,链接器将忽略库中的 symbol_foo
;它已经有一个定义,不需要另一个。但是,libfoo.a
库中包含symbol_foo
的目标文件很可能还定义了一些其他符号,而链接器需要这些其他符号,所以它有链接包含 symbol_foo
的目标文件,并提示因为该符号是双重定义的,即使同一文件中的其他符号不是。
Plauger 提倡(静态)库中的每个目标文件都应该定义一个外部符号。这允许库中函数的最大可替换性。我相信可以公平地假设 libfoo.a
的设计者没有做出那个决定,至少 w.r.t symbol_foo
。
您可以从libfoo.a
中提取目标文件(使用临时目录)并使用nm
检查它们的内容;您可以直接在库本身上执行此操作。与适当的选项一起使用,将向您显示哪些文件定义和引用了哪些其他符号。
请注意,与共享库链接的规则有些不同。还有可以改变行为的“弱”符号。您还可以经常从多个目标文件创建“可重定位”或“可重新链接”的目标文件(通常是 ld -r
);这给了你一个更大的目标文件并改变了等式。最后,就目前而言,链接描述文件可以控制哪些符号在库外可见。所以,这只不过是对这个主题的掩饰。
关于我可以用我自己的版本替换静态库中的符号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51749969/