我试图在两台x86单独的机器上编译相同的库。两者使用相同的工具链(完全相同的一组文件),但有不同的Glibc版本。
当我运行命令LD_DEBUG=libs /lib64/ld-linux-x86-64.so.2 --list ./libl2ps.so时,我注意到两个Linux加载程序之间存在以下差异:
Machine 1 (使用Glibc 2.12):
19943: find library=libm.so.6 [0]; searching
19943: search path=/ebs/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64:...:/ebs/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/. (RPATH from file ./libl2ps.so)
19943: trying file=/ebs/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.so.6
19943:
19943: find library=libgcc_s.so.1 [0]; searching
...在本例中,loader基于lib libm.so.6的RPATH从工具链路径中选择lib libl2ps.so。
Machine 2 (使用Glibc 2.17):
10699: find library=libm.so.6 [0]; searching
10699: search path=/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:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib:/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/. (RPATH from file ./libl2ps.so)
10699: trying file=/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.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64/libm.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib/libm.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/./libm.so.6
10699: search cache=/etc/ld.so.cache
10699: trying file=/lib64/libm.so.6至于Machine1,加载程序试图从libl2ps.so的RPATH中选择工具链路径中的lib libm.so.6,但出于某种原因而跳过它,然后再尝试其他路径。最后,从系统路径libm.so.6中选择/lib64/。
两个libs lib2ps.so的RPATH完全相同。这两个文件libm.so.6在两台机器上也完全相同(用md5sum检查)。
我不理解两个Linux加载器之间的行为差异。你认为有什么原因可以解释这种差异吗?
非常感谢你的回答。
更新:
谢谢yugr的回答。
readelf -h的输出只给出字段“入口点地址”和“节头的开始”上的差异,并且没有其他差异,所以我认为这不会有帮助。
关于使用dlopen()/dlerror(),我使用以下语句执行了一些可执行文件:
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.so 在我的文件系统中确实存在:
$ 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:
的确,我没有指出机器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那么,如何解释这个设置为4.4.0的ABI版本号呢?
谢谢
谢谢你的回答!我将通过在机器2上升级我的内核版本来尝试它。
谢谢问候
发布于 2018-10-12 14:34:12
您看到的错误消息是臭名昭著的混乱的ENOENT errno。我在dl-load.c中看到了它的两个实例
我怀疑第一个在您的情况下失败了,这意味着操作系统内核在两台机器之间是不兼容的。ld.so 命令页确实说过
每个共享对象都可以通知动态链接器它所需的最小内核ABI版本。(此需求被编码在ELF备注部分中,该部分可通过readelf -n作为标记为NT_GNU_ABI_TAG的部分查看。)在运行时,动态链接器确定正在运行的内核的ABI版本,并拒绝加载指定超过该ABI版本的最小ABI版本的共享对象。
NT_GNU_ABI_TAG为4.4.0,这意味着运行一个程序,期望3.10内核上至少有一个4.4内核。理论上,较新的Glibc也应该运行在较老的内核上,但在您的示例中,Glibc很可能是使用显式--enable-kernel标志构建的,这防止了它在4.4之前的内核上使用(例如,这一解释 of --enable-kernel)。
作为一种解决办法,您可以尝试通过以下方式覆盖机器2上的内核版本来欺骗Glibc。
export LD_ASSUME_KERNEL=4.4.0但是,如果libm开发了3.10中没有真正出现的4.4特定的系统,那么它可能就行不通了。
https://stackoverflow.com/questions/52768524
复制相似问题