ldd 输出中的多个 GLIBC 版本意味着什么?

ldd 输出中的多个 GLIBC 版本意味着什么?

ldd 程序报告缺少我的共享库所需的一些共享库。 (我在另一台装有 Red Hat Linux 7 的计算机上构建了它,并希望在另一台装有 Red Hat Linux 6 的计算机上运行它。)

在下面的“版本信息”部分中,有 libc.so.6 的三个条目;每个版本后面的括号中都有不同的版本(GLIBC_2.14、GLIBC_2.4 和 GLIBC_2.2.5)。其中第一个没有在计算机上安装关联的共享库。

我是 Linux 新手,不明白如何解释这个输出,更不用说解决问题了。下面是命令和输出。

>ldd -v libAtlasUtilsPB.so
./libAtlasUtilsPB.so: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./libAtlasUtilsPB.so)
./libAtlasUtilsPB.so: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by ./libAtlasUtilsPB.so)
./libAtlasUtilsPB.so: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by ./libAtlasUtilsPB.so)
    linux-vdso.so.1 =>  (0x00007fffa3dff000)
    librt.so.1 => /lib64/librt.so.1 (0x00007fea7a7b2000)
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fea7a4ab000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fea7a227000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fea7a011000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fea79df3000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fea79a5f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fea7ad17000)

    Version information:
    ./libAtlasUtilsPB.so:
            libgcc_s.so.1 (GCC_3.0) => /lib64/libgcc_s.so.1
            libm.so.6 (GLIBC_2.2.5) => /lib64/libm.so.6
            libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0
            libc.so.6 (GLIBC_2.14) => not found
            libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
            libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
            libstdc++.so.6 (GLIBCXX_3.4.18) => not found
            libstdc++.so.6 (GLIBCXX_3.4.15) => not found
            libstdc++.so.6 (GLIBCXX_3.4.9) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (GLIBCXX_3.4.11) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (CXXABI_1.3) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (GLIBCXX_3.4) => /usr/lib64/libstdc++.so.6

答案1

ldd列出其参数所需的共享库。使用该-v选项,它会列出所有可用信息,包括版本符号。

表格的线条

linux-vdso.so.1 =>  (0x00007fffa3dff000)
librt.so.1 => /lib64/librt.so.1 (0x00007fea7a7b2000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fea7a4ab000)

列出 所需的库libAtlasUtilsPB.so以及它们是如何解析的;在你的情况下所有必需的图书馆被发现。linux-vdso.so.1很特别,它是虚拟图书馆由内核提供。

表格的线条

libgcc_s.so.1 (GCC_3.0) => /lib64/libgcc_s.so.1
libm.so.6 (GLIBC_2.2.5) => /lib64/libm.so.6
libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0

列出 所需的版本符号libAtlasUtilsPB.so,以及它们的解析方式。这是ldd无法解析项目的地方,它通过在此处指示“未找到”并在输出开始时打印错误消息来指示。

GLIBC_...GLIBCXX_...是版本符号,在某些库(包括GNU C库和GCC库)中使用它们来标识所需的版本并管理向后兼容性。二进制文件(可执行文件或库)通常最终需要多个版本,具体取决于它实际使用的目标库中的符号。为了满足给定二进制文件的要求,您需要提供一个支持所有所需版本的库 -IE至少匹配需求列表中最高版本符号的库。

最终可能需要多个版本的原因是每个导入的对象(函数等)都可以有一个版本,并且给定的二进制文件可以链接到它使用的所有函数的多个版本。例如,在我的系统上选择一个具有两个版本的示例/lib/x86_64-linux-gnu/libgcc_s.so.1ldd -v显示

/lib/x86_64-linux-gnu/libgcc_s.so.1:
        libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6

libgcc_s.so.1需要来自 的两个版本符号libc.so.6。为了找出原因,我们需要查看它包含的未定义符号 - 这些是它需要导入的符号:

$ objdump -T /lib/x86_64-linux-gnu/libgcc_s.so.1|grep -F '*UND*'
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 dl_iterate_phdr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000  w   D  *UND*  0000000000000000              __pthread_key_create
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strlen
0000000000000000  w   D  *UND*  0000000000000000              pthread_getspecific
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memset
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 calloc
0000000000000000  w   D  *UND*  0000000000000000              pthread_key_create
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14  memcpy
0000000000000000  w   D  *UND*  0000000000000000              pthread_once
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 pthread_mutex_unlock
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 malloc
0000000000000000  w   D  *UND*  0000000000000000              pthread_setspecific
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 realloc
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 pthread_mutex_lock

这列出了许多版本化符号(那些带有GLIBC_2.2.5GLIBC_2.14在倒数第二列中的符号),我们可以在这里看到这些版本与我们看到的ldd.为什么我们最终会得到多个版本符号?这就是向后兼容性发挥作用的地方。版本 2.2.5 是 GNU C 库中符号版本控制的基线; 2.2.5 版本中存在的任何函数都带有该版本。在 GNU C 库 2.13 版本中, 的行为memcpy发生了改变;这破坏了许多程序,因此在 2.14 版本中,使用可选版本标签放置了向后兼容的版本GLIBC_2.2.5,并添加了带有版本标签的新版本GLIBC_2.14。因此,使用早期版本的 C 库构建的旧二进制文件使用旧版本的memcpy,而使用 2.14 版及更高版本构建的二进制文件则使用新版本的memcpy

同样的故事也适用于libstdc++.so.6,但随着版本号的更新,有更多的变化;手册libstdc++提供了详细信息

在你的情况下,你需要libstdc++.so.6匹配GLIBCXX_3.4.18IEGCC 4.8.0 或更高版本提供的版本以及 GNU C 库的 2.14 版本。

您无法轻松地在 RHEL 7 上构建二进制文件并在 RHEL 6 上运行它们(这就是主要版本不同的原因)。你最好在 RHEL 6 上重建你的程序......

相关内容