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
这是我的问题:
为什么/lib32/libc.so.6 中有两个 fopen 符号?应该禁止在同一个目标文件中使用相同的符号,对吧?
为什么 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/