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
Run Code Online (Sandbox Code Playgroud)
这是我的问题:
为什么/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继续使用libfoo.so.1旧ABI 之前链接的应用程序,以及与新ABI 一起使用的新应用程序libfoo.so.2.
这是所有的一些细节描述在这里.
但是后来glibc引入了一个扩展,而不是引入一个全新的库(与前一个版本共享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及更新版本链接的二进制文件使用new struct FILE和call _IO_new_fopen(其中fopen@GLIBC_2.1包含别名).
这@@只是一个显示当前默认符号版本的符号.