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

时间:2013-06-02 07:44:50

标签: c++ linux centos

根据gcc ABI政策,gcc 4.4.7应该依赖于libstdc ++ 6.0.13。据我所知,编译器版本和libstdc ++版本是相互关联的,无法交换,因此我发现以下事实让我惊讶:

  • CentOS 5.8设法有一个链接6.0.8的gcc44软件包,显然是默认系统(基于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 )
  • 的文本文件

这里发生了什么样的魔法?

具体做法是:

  • 他们怎么能提供链接旧版libstdc ++的gcc 4.4.7?我认为这是不可能的。
  • 这个stdc ++ _非共享库是什么?
  • 我不知道.so文件可能包含该文本。谁解析它(我想是动态链接器)以及它的规格和后果是什么?
  • 这魔法可以走多远?我可以在libstdc ++ 6.0.3中使用gcc4.7吗?什么是兼容性范围

1 个答案:

答案 0 :(得分:15)

  

这里发生了什么样的魔法?

这主要是ELF符号版本的魔力。我在此看到的最佳参考是Ulrich Drepper的How to Write Shared Libraries,特别是第3部分。

  

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

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

查看libstdc ++的ABI compatibility page,您可以看到GCC 4.1的libstdc ++有GLIBCXX_3.4.8而GCC 4.4的库存(FSF版本)有GLIBCXX_3.4.13。然后可以查看libstdc++ version scripts以查看在这两个版本之间添加了哪些符号。

查看符号版本的更经验的途径是使用像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 ++ _非共享库是什么?

加入上一段中的点,stdc ++ _非共享是一个静态库,其中包含库存libstdc ++。so.6.0.13中的符号,但不包含在libstdc ++中的符号.so.6.0.8。

  

我不知道.so文件可能包含该文本。谁解析它(我想是动态链接器)以及它的规格和后果是什么?

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

这样做的缺点是,以这种方式编译的应用程序会比同一个应用程序更加臃肿,该应用程序仅动态链接到库存libstdc ++。so.6.0.13,其中包含所有必需的符号。好处是,较新标准库的功能可用于旧系统的标准安装,而独立软件供应商无需发送自己的libstdc ++副本。

  

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

既然你知道它的神奇之处,那么你可能会意识到你拥有的这个版本的GCC 4.4是一个专为Centos 5制作的特别版本(原来是Red Hat 5)。因此,您可以创建一个GCC 4.7,它将生成仅需要libstdc ++ 6.0.3的二进制文件,但是需要修补GCC树的大量工作才能将正确的符号放入stdc ++ _ nonshared.a中。您至少可以查看gcc44 RPM的来源,了解Red Hat是如何在那里完成的。

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