Linker Glibc 2.12和Glibc 2.17之间Linux加载程序(ld-Linux-x86-64)的行为差异

Linker Glibc 2.12和Glibc 2.17之间Linux加载程序(ld-Linux-x86-64)的行为差异,linker,shared-libraries,glibc,ldd,rpath,Linker,Shared Libraries,Glibc,Ldd,Rpath,我试图在两台x86不同的机器上编译相同的库。 两者都使用相同的工具链(完全相同的文件集),但有不同的Glibc版本 当我运行命令LD_DEBUG=libs/lib64/LD-linux-x86-64.so.2--list./libl2ps.so时,我注意到两个linux加载程序之间存在以下差异: 机器1(带Glibc 2.12): 在这种情况下,Linux加载程序根据liblibl2ps.so的RPATH从工具链路径中选择liblibm.so.6 机器2(带Glibc 2.17): 对于机器1,

我试图在两台x86不同的机器上编译相同的库。 两者都使用相同的工具链(完全相同的文件集),但有不同的Glibc版本

当我运行命令
LD_DEBUG=libs/lib64/LD-linux-x86-64.so.2--list./libl2ps.so
时,我注意到两个linux加载程序之间存在以下差异:

机器1(带Glibc 2.12):

在这种情况下,Linux加载程序根据lib
libl2ps.so
的RPATH从工具链路径中选择lib
libm.so.6

机器2(带Glibc 2.17):

对于机器1,加载程序尝试从RPATH of
libl2ps.so
从工具链路径选择lib
libm.so.6
,但出于某种原因跳过它,然后尝试其他路径。最后,它从系统路径
/lib64/
中选择
libm.so.6

两个lib的RPATH
lib2ps.so
完全相同。这两个文件
libm.so.6
在两台机器上也完全相同(用
md5sum
检查)

我不理解这两个Linux加载程序之间的行为差异。 你认为有什么原因可以解释这种差异吗

非常感谢你的回答

更新:

$ readelf -n libm.so.6 

Notes at offset 0x00000238 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 0d84c7247dd76008c096719043e5592735a1c4bd

Notes at offset 0x0000025c with length 0x00000020:
  Owner                 Data size   Description
  GNU                  0x00000010   NT_GNU_ABI_TAG (ABI version tag)
  OS: Linux, ABI: 4.4.0
谢谢你的回答

readelf-h
的输出只给出了“入口点地址”和“节头开始”字段上的差异,没有其他差异,所以我认为这不会有帮助

关于使用
dlopen()

dlopen("/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so", RTLD_LAZY);
在机器1上,它按预期工作:

C++ dlopen demo

Opening libm-2.28.so...
Closing library...
在机器2上,它发生故障,并且dlerror()给出以下输出:

Cannot open library: /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so: cannot open shared object file: No such file or directory
但是文件
libm-2-28。因此
确实存在于我的文件系统中

$ ls -l /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so
-rwxr-xr-x 1 frperies linseeusers_lte_espoo 1682944 Oct  5 13:50 /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic- linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so
这很奇怪,什么会导致这种情况

谢谢

更新2:

$ readelf -n libm.so.6 

Notes at offset 0x00000238 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 0d84c7247dd76008c096719043e5592735a1c4bd

Notes at offset 0x0000025c with length 0x00000020:
  Owner                 Data size   Description
  GNU                  0x00000010   NT_GNU_ABI_TAG (ABI version tag)
  OS: Linux, ABI: 4.4.0
的确,我没有指出机器1是RHEL6.8发行版,而机器2是RHEL7.4发行版。我(天真地)认为这并不重要

在机器1上:

$ cat /proc/sys/kernel/osrelease
4.4.115-1.NSN.el6.x86_64

$ uname -a
Linux sq24-3 4.4.115-1.NSN.el6.x86_64 #1 SMP Mon Feb 12 12:35:46 CET 2018 x86_64 x86_64 x86_64 GNU/Linux

$ readelf -n libl2ps.so 

Notes at offset 0x00000270 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: b598468830fdf2f61eda25553b9a367c4d28cdc9
在机器2上:

$ cat /proc/sys/kernel/osrelease
3.10.0-693.el7.x86_64

$ uname -a
Linux localhost.localdomain 3.10.0-693.el7.x86_64 #1 SMP Thu Jul 6 19:56:57 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

$ readelf -n libl2ps.so 

Displaying notes found at file offset 0x00000270 with length 0x00000024:
  Owner                 Data size   Description 
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 5829181bc0502233748149369108915ea7b10e8f
有帮助吗

谢谢

更新3:

$ readelf -n libm.so.6 

Notes at offset 0x00000238 with length 0x00000024:
  Owner                 Data size   Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
  Build ID: 0d84c7247dd76008c096719043e5592735a1c4bd

Notes at offset 0x0000025c with length 0x00000020:
  Owner                 Data size   Description
  GNU                  0x00000010   NT_GNU_ABI_TAG (ABI version tag)
  OS: Linux, ABI: 4.4.0
那么,如何解释ABI版本号设置为4.4.0

谢谢

谢谢yugr和Employed Russian的回答!! 我将尝试在机器2上升级我的内核版本

谢谢
关于

您看到的错误消息是臭名昭著的令人困惑的
enoint
errno。我在
dl load.c
中看到了它的两个实例:

我怀疑在您的案例中第一个失败,这意味着操作系统内核在两台机器之间不兼容<代码>ld。所以
确实这么说

每个共享对象都可以通知动态链接器 所需的最低内核ABI版本。(本 需求编码在可查看的ELF注释部分 在运行时通过readelf-n作为标记为NT_GNU_ABI_TAG.)的部分 此时,动态链接器确定 正在运行内核并将拒绝加载 指定超出该ABI版本的最小ABI版本

NT_GNU_ABI_TAG
是4.4.0,这意味着在3.10内核上运行一个至少需要4.4内核的程序。从理论上讲,较新的Glibc也应该在较旧的内核上运行,但在您的例子中,Glibc很可能是使用显式的
--enable kernel
标志构建的,该标志阻止它在4.4之前的内核上使用(例如,请参见
--enable kernel

作为一种解决方法,您可以尝试通过以下方式覆盖机器2上的内核版本来愚弄Glibc

export LD_ASSUME_KERNEL=4.4.0

但是,如果
libm
进行4.4特定的系统调用,而这些调用在3.10中并不存在,那么它可能无法工作。

Glibc在加载时执行一系列检查(请参阅),很难说哪一个失败了。您可以发布
readelf-h
的输出吗?您是否可以尝试在可执行文件中使用
dlopen
ing您的库(通过绝对路径)并在失败时检查
dlerror
?嗨,yugr,谢谢您的回答…请阅读上面的更新。您想运行
readelf-n…/libm.so.6
,因为加载程序拒绝使用该库。
libl2ps.so
上的注释是不相关的。@EmployedRussian:你说得对,很抱歉这个错误。请参阅更新3…@fPeries好的,我们可能就快到了。在编译有问题的
libm.so
的机器上,
uname
的输出是什么?不幸的是,我没有这些信息,因为这个文件libm.so附带了在第三台独立机器上构建的整个工具链。我认为它与机器1的内核版本非常一致。请参考更新3,原来libm.so的ABI号是4.4.0,但我真的不知道它是什么意思。。。thanks@frperies答案现在解释了4.4.0的含义——它是这个GLIBC版本兼容的最低Linux内核版本。您必须升级内核,或者使用
--enable kernel=3.10
重建sysroot GLIBC。感谢您给出了非常清晰的答案!我不知道这些方面以及Glibc和Kernel/ABI版本之间的底层交互。