二进制 elf DT_RUNPATH 中存在的库未被选择?

二进制 elf DT_RUNPATH 中存在的库未被选择?

我已在我的环境中定制gcc-4.7.2。系统 gcc 是gcc-4.3.4

我已经修补了DT_RUNPATH对于我所有自定义的 gcc 二进制文件和共享库使用patchelf --set-rpath

但是,当我ldd在 4.7.2 上运行时cc1,它会选择系统libstdc++,而不是DT_RUNPATH

$ ldd /sdk/x86_64/2.11.1/gcc-4.7.2/libexec/gcc/x86_64-suse-linux/4.7.2/cc1
        libcloog-isl.so.1 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libcloog-isl.so.1 (0x00007f072dce8000)
        ...
        libc.so.6 => /lib64/libc.so.6 (0x00007f072bfe0000)
   -->  libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f072bcd5000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f072babe000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f072df0d000)

可以看出DT_RUNPATH指定gcc-4.7.2库位置:

$ readelf -a /sdk/x86_64/2.11.1/gcc-4.7.2/libexec/gcc/x86_64-suse-linux/4.7.2/cc1 | grep PATH
 0x000000000000001d (RUNPATH)            Library runpath: \
    [/sdk/x86_64/2.11.1/gcc-4.7.2/lib64: \
     /sdk/x86_64/2.11.1/gcc-4.7.2/lib: \
     /sdk/x86_64/2.11.1/gcc-4.7.2/libexec/gcc/x86_64-suse-linux/lib64: \
     /sdk/x86_64/2.11.1/gcc-4.7.2/lib/gcc/x86_64-suse-linux/4.7.2]

我知道libstdc++.so.6在第一个条目中存在DT_RUNPATH

$ ls -l /sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so*
lrwxrwxrwx .../sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so -> libstdc++.so.6.0.17
lrwxrwxrwx .../sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so.6 -> libstdc++.so.6.0.17
-rwxr-x--- .../sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so.6.0.17
-rwxr-x--- .../sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so.6.0.17-gdb.py

我没有LD_LIBRARY_PATH在我的环境中设置:

$ echo $LD_LIBRARY_PATH

$

如果我LD_LIBRARY_PATH然后它找到正确的库:

export LD_LIBRARY_PATH=/sdk/x86_64/2.11.1/gcc-4.7.2/lib64: \
    /sdk/x86_64/2.11.1/gcc-4.7.2/lib: \
    /sdk/x86_64/2.11.1/gcc-4.7.2/libexec/gcc/x86_64-suse-linux/lib64: \
    /sdk/x86_64/2.11.1/gcc-4.7.2/lib/gcc/x86_64-suse-linux/4.7.2

$ ldd /sdk/x86_64/2.11.1/gcc-4.7.2/libexec/gcc/x86_64-suse-linux/4.7.2/cc1
        libcloog-isl.so.1 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libcloog-isl.so.1 (0x00007f072dce8000)
        ...
        libc.so.6 => /lib64/libc.so.6 (0x00007f072bfe0000)
   -->  libstdc++.so.6 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libstdc++.so.6 (0x00007fdf4e560000)
        libgcc_s.so.1 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib64/libgcc_s.so.1 (0x00007fdf4e34b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f072df0d000)
  • 为什么它没有找到在DT_RUNPATH
  • 我怎样才能强制它使用gcc-4.7.2没有必须使用LD_LIBRARY_PATH

答案1

问题在于,其中一个先决条件 ( libppl.so) 也导入了libstdc++。该先决条件是使用系统 gcc 构建的,因此会发现/usr/lib64/libstdc++.so.6

$ ldd /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libppl.so
        linux-vdso.so.1 =>  (0x00007fffd10db000)
        libgmpxx.so.4 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libgmpxx.so.4 (0x00007f4716f92000)
        libgmp.so.10 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libgmp.so.10 (0x00007f4716d26000)
    --> libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f4716a25000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f47167a0000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f4716441000)
        libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007f471622c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f47174b4000)

一旦动态链接器找到一个库,就不再搜索它;该位置将用于任何后续要求。

我解决了这个问题使用新的 gcc 重建先决条件

$ ldd /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libppl.so
        linux-vdso.so.1 =>  (0x00007fffd10db000)
        libgmpxx.so.4 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libgmpxx.so.4 (0x00007f4716f92000)
        libgmp.so.10 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/libgmp.so.10 (0x00007f4716d26000)
    --> libstdc++.so.6 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/../lib64/libstdc++.so.6 (0x00007f4716a25000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f47167a0000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f4716441000)
        libgcc_s.so.1 => /sdk/x86_64/2.11.1/gcc-4.7.2/lib/../lib64/libgcc_s.so.1 (0x00007f471622c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f47174b4000)

我认为最后一步是使用新建的先决条件重建 gcc。

  • 使用系统 gcc 构建先决条件
  • 建立新的 gcc
  • 使用新的 gcc 重建先决条件
  • 使用重建的先决条件重建 gcc

我不确定最后一步是否有必要。

相关内容