我可以用我自己的版本替换静态库中的符号吗?

标签 c linker

使用 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/

相关文章:

c - 全局空间中的指针初始化 C 语句如何在编译/链接时获取其分配的值?

c++ - 在 xcode 中构建时出错

c - 如何在system()中使用C代码变量

c - 如何在运行时找到全局变量的地址?

c - struct epoll_event memset 还是没有 memset?

dll - 在DLL中转发数据

c - 结构体和变量的大小

c - 错误 : called object ‘0’ is not a function

linker - 为什么 "/lib/libc.so.1"挂载在solaris 10上?

visual-studio-2010 - VS2010 C++ 项目 : links fine in debug, 中的 NODEFAULTLIB 噩梦无法在发行版中找到一致的库集