linux - 为什么/lib32/libc.so.6 中有两个 "fopen"符号?

标签 linux nm readelf

nm -D /lib32/libc.so.6 | grep '\<fopen\>'
0005d0c0 T fopen
00109750 T fopen

readelf -s  /lib32/libc.so.6 | egrep '0005d0c0|00109750'
181: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 fopen@@GLIBC_2.1
182: 00109750   136 FUNC    GLOBAL DEFAULT   12 fopen@GLIBC_2.0
679: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 _IO_fopen@@GLIBC_2.1
680: 00109750   136 FUNC    GLOBAL DEFAULT   12 _IO_fopen@GLIBC_2.0

这是我的问题:

  1. 为什么/lib32/libc.so.6 中有两个 fopen 符号?应该禁止在同一个目标文件中使用相同的符号,对吧?

  2. 为什么 readelf -s 转储出 fopen@@GLIBC_2.1 和 fopen@GLIBC_2.0 而不是 fopen?

谢谢

最佳答案

为了了解这里发生的事情,您首先需要了解传统上如何处理二进制兼容性。

过去的机制是“外部版本控制”。您从 libfoo.so.1 开始,当您需要更改现有函数的 ABI 时,您不得不引入 libfoo.so.2

libfoo.so.2 之前链接的应用程序继续使用具有旧 ABI 的 libfoo.so.1,而新应用程序使用 libfoo .so.2 使用新的 ABI。

这一切都有一些详细的描述 here .

但随后 glibc 引入了一个 extension , 而不是引入一个全新的库(与以前的版本共享 99% 的代码),而是将一个新的符号引入现有的库中。

该扩展允许 libc.so.6 中保持版本 6,同时允许旧的二进制文件工作,并使 ABI 得到发展。

fopen 的特殊情况下,在 glibc 2.1 版中对 struct FILE 进行了不兼容更改。在 glibc-2.0 系统上链接的二进制文件继续使用旧的 struct FILE(当时唯一可用的),并继续调用 _IO_old_fopen(为此 fopen@GLIBC_2.0 是一个别名)。针对 glibc-2.1 和更新版本链接的二进制文件使用新的 struct FILE,并调用 _IO_new_fopen(fopen@GLIBC_2.1 是别名) .

@@ 只是一个表示当前默认 符号版本的符号。

关于linux - 为什么/lib32/libc.so.6 中有两个 "fopen"符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9156414/

相关文章:

linux - ELF的基址

c - 静态库中外部符号的预期签名

binutils - nm 和 objdump 之间的区别

linux - 使用 awk 解析 nm 命令的输出 - Linux Bash

linux - readelf 与 objdump : why are both needed

php - 访问根目录之外的文件

linux - 在 KornShell 中检查大小大于零的多个文件

gdb - 如何从elf文件中提取函数原型(prototype)?

linux - 使用 sed 在文件中插入一些文本

c - 为什么 register_tm_clones 和 deregister_tm_clones 引用的地址超过 .bss 部分?这个内存分配在哪里?