首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Glibc 2.12和Glibc 2.17之间Linux加载程序(ld-linux-x86-64)行为的差异

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

Stack Overflow用户
提问于 2018-10-11 20:33:42
回答 1查看 585关注 0票数 0

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

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

Machine 1 (使用Glibc 2.12):

代码语言:javascript
复制
 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):

代码语言:javascript
复制
 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(),我使用以下语句执行了一些可执行文件:

代码语言:javascript
复制
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上,它按预期工作:

代码语言:javascript
复制
C++ dlopen demo

Opening libm-2.28.so...
Closing library...

在机器2上,它失败了,dlerror()给出了以下输出:

代码语言:javascript
复制
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 在我的文件系统中确实存在

代码语言:javascript
复制
$ 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上:

代码语言:javascript
复制
$ 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上:

代码语言:javascript
复制
$ 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:

代码语言:javascript
复制
$ 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上升级我的内核版本来尝试它。

谢谢问候

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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。

代码语言:javascript
复制
export LD_ASSUME_KERNEL=4.4.0

但是,如果libm开发了3.10中没有真正出现的4.4特定的系统,那么它可能就行不通了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52768524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档