CentOS 5.8与gcc 4.4.7链接libstdc++ 6.0.8.这怎么可能

CentOS 5.8 with gcc 4.4.7 links against libstdc++ 6.0.8. How is it possible?

本文关键字:怎么可能 libstdc++ gcc CentOS 链接      更新时间:2023-10-16

根据gcc ABI策略,gcc 4.4.7应该依赖于libstdc++ 6.0.13。据我所知,编译器版本和libstdc++版本是紧密相关的,不能互换,所以我惊讶地发现了以下事实:

    CentOS 5.8设法有一个gcc44包链接到6.0.8,显然是默认系统(基于gcc-4.1.2)
  • 表示libstdc++。所以在编译器目录(/usr/lib/gcc/x86_64-redhat-linux6E/4.4.7,我期望找到libstdc++-6.0.13)不是链接到任何类型的共享对象,而是包含INPUT ( -lstdc++_nonshared /usr/lib64/libstdc++.so.6 )的文本文件

这里发生了什么魔法?

专:

  • 他们怎么能提供一个gcc 4.4.7来链接旧版本的libstdc++?我认为这是不可能的。
  • 这个stdc++_nonshared库是什么?
  • 我不知道。so文件可以包含这个文本。谁解析它(我猜是动态链接器),它的规范和结果是什么?
  • 这魔法能走多远?我可以使用gcc4.7与libstdc++ 6.0.3?什么是兼容性谱

这里发生了什么魔法?

这主要是ELF符号版本控制的魔力。在这方面我看到的最好的参考是Ulrich Drepper的《如何编写共享库》,特别是第3节。

他们怎么能提供一个gcc 4.4.7来链接旧版本的libstdc++呢?我认为这是不可能的。

libstdc++开发人员非常注意ABI兼容性。这使得查看两个不同版本的libstdc++之间引入的新符号变得相当简单。

查看libstdc++的ABI兼容性页面,您可以看到GCC 4.1的libstdc++有GLIBCXX_3.4.8,而GCC 4.4的股票(FSF发行版)有GLIBCXX_3.4.13。然后可以查看libstdc++版本脚本,以查看在这两个版本之间添加了哪些符号。

查看符号版本的更经验性的方法是使用readelf这样的工具。例如,在我的Ubuntu系统上,readelf --dyn-syms --wide /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt显示的输出是这样的(只是几个选定的短行):

223: 000000000006dbe0  2121 FUNC    GLOBAL DEFAULT   12 std::ios_base::Init::Init()@@GLIBCXX_3.4
...
226: 00000000002ed920     1 OBJECT  GLOBAL DEFAULT   27 std::adopt_lock@@GLIBCXX_3.4.11

注意符号名称后面的符号版本,在@@后面。

stdc++_nonshared库是什么?

连接上一段的点,stdc++_nonshared是一个静态库,它包含了libstdc++.so.6.0.13中而不是libstdc++.so.6.0.8中的符号。

我不知道。so文件可以包含这个文本。谁解析它(我猜是动态链接器),它的规范和结果是什么?

常规链接器会解析这个,而不是运行时链接器。请参阅binutils文档中的链接器脚本中的INPUT。因此,链接到这个特殊的libstdc++.so.6.0.13将导致链接器动态链接到libstdc++.so.6.0.8,并静态链接到包含额外符号的库。

这样做的缺点是,与仅动态链接到包含所有必要符号的库存libstdc++.so.6.0.13的相同应用程序相比,以这种方式编译的应用程序会稍微臃肿一些。好处是新标准库的特性可以在旧系统的标准安装上使用,而不需要独立软件供应商提供他们自己的libstdc++副本。

这魔法能走多远?我可以使用gcc4.7与libstdc++ 6.0.3?兼容性的范围是什么

现在你知道了魔法是什么,也许你能理解这个版本的GCC 4.4是一个专门为Centos 5制作的特殊版本(好吧,最初是Red Hat 5)。所以也许你可以创建一个GCC 4.7,它只需要libstdc++ 6.0.3的二进制文件,但是它需要大量的工作来修补你的GCC树,把正确的符号放在stdc++ _nonshareda中。您至少可以查看gcc44 RPM的源代码,了解Red Hat在那里是如何做到的。

Red Hat似乎在他们的Red Hat Developer Toolset中延续了这种方法。在撰写本文时,GCC 4.8.1是最新的编译器,它可以为EL5构建二进制文件,这仍然只需要在目标系统上安装libstdc++.so.6.0.8。对于想要用c++ 11编写程序,但又需要能够部署在EL5或EL6上的开发人员来说,这是非常好的。