Gcc 为什么针对已安装的glibc编译的程序不能正常运行?
提前谢谢 我的开发环境:Gcc 为什么针对已安装的glibc编译的程序不能正常运行?,gcc,linker,shared-libraries,elf,glibc,Gcc,Linker,Shared Libraries,Elf,Glibc,提前谢谢 我的开发环境: $ cat /proc/version Linux version 5.4.0-66-generic (buildd@lgw01-amd64-016) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #74~18.04.2-Ubuntu SMP Fri Feb 5 11:17:31 UTC 2021 $ ld --version GNU ld (GNU Binutils for Ubuntu) 2.30 Copyri
$ cat /proc/version
Linux version 5.4.0-66-generic (buildd@lgw01-amd64-016) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #74~18.04.2-Ubuntu SMP Fri Feb 5 11:17:31 UTC 2021
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.30
Copyright (C) 2018 Free Software Foundation, Inc.
$ getconf GNU_LIBC_VERSION
glibc 2.27
$ #my glibc source version is 2.32.9000-development
$ cat ./version.h
/* This file just defines the current version number of libc. */
#define RELEASE "development"
#define VERSION "2.32.9000"
出于某些原因,我需要修改和测试glibc。我按照本网站()的步骤修改glibc并编写测试程序
$ ldd ./exec/1-1.out
linux-vdso.so.1 (0x00007ffcbf367000)
libpthread.so.0 => /home/cjl-target/gnu/install/lib64/libpthread.so.0 (0x00007fcadcea9000)
libc.so.6 => /home/cjl-target/gnu/install/lib64/libc.so.6 (0x00007fcadcaed000)
/home/cjl-target/gnu/install/lib64/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fcadd2ca000)
如上所示,程序所依赖的共享库都指向glibc安装路径。
但当我编译消息队列的测试程序(test mq_unlink)并运行它时,失败如下:
./exec/1-1.out: symbol lookup error: /lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_vfork, version GLIBC_PRIVATE
检查程序所依赖的库:
$ ldd ./exec/1-1.out
linux-vdso.so.1 (0x00007ffce3f72000)
librt.so.1 => /home/cjl-target/gnu/install/lib64/librt.so.1 (0x00007f0a389a2000)
libc.so.6 => /home/cjl-target/gnu/install/lib64/libc.so.6 (0x00007f0a385e6000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0a383c7000)
/home/cjl-target/gnu/install/lib64/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f0a38dac000)
如上所示,共享库libpthread.so.0指向系统库。为什么?
我的编译脚本是(来自上面的网站):
编译pthread的测试程序时:/dobuild 1-1.c-pthread-Wall
当我编译mq的测试程序时:/dobuild 1-1.c-lrt-Wall
此外,令人困惑的是,当调用mq_unlink的测试程序中创建的pthread_时,编译它/dobuild 1-1.c-lrt-pthread
,ldd结果显示所有依赖库都指向已安装的glibc。
我尝试过多种不同的方法,但似乎都不管用。有什么想法吗?首先,您应该停止使用
ldd
——在主机上存在多个glibc的情况下,ldd
更可能误导而不是照亮
如果要查看实际加载的库,请执行以下操作:
LD_TRACE_LOADED_OBJECTS=1 ./exec/1-1.out
其次,您几乎不应该在shell脚本中使用$*
。请改用“$@”(注意:引号很重要)。看这个
第三,你观察到的行为很容易解释。要理解它,您需要知道所描述的DT_RPATH
和DT_RUNPATH
之间的区别
您可以验证二进制文件当前是否正在使用运行路径,如下所示:
readelf -d 1-1.out | grep 'R.*PATH'
您可以通过向link命令添加-Wl,--disable new dtags
(这将导致二进制文件改用RPATH
)来验证一切是否按预期开始工作
总结如下:
影响对二进制文件本身的搜索,但不影响对二进制文件所依赖的任何库的搜索RUNPATH
影响二进制文件及其所依赖的所有库的搜索路径RPATH
- 使用
,仅当二进制文件直接依赖于它时,才会找到预期的运行路径
,但当对libpthread.so.0
的依赖是间接的(通过libpthread
)时,则不会找到该文件librt
- 使用
,无论依赖关系是直接的还是间接的,都会找到预期的RPATH
libpthread.so.0
-rpath=${SYSROOT}/lib64
链接librt.so
您可以编辑rt/Makefile
,或使用以下内容生成:
make LDFLAGS-rt.so='-Wl,--enable-new-dtags,-z,nodelete,-rpath=${SYSROOT}/lib64'
对于可能对GLIBC的其他部分产生可传递依赖性的任何其他库,您都需要这样做。我不知道有什么通用的方法可以做到这一点,但是设置
LDFLAGS lib.so='-Wl,-rpath=${SYSROOT}/lib64'
并重建一切可能会奏效。首先,您应该停止使用ldd
——在主机上存在多个glibc的情况下,ldd
更可能误导而不是照亮
如果要查看实际加载的库,请执行以下操作:
LD_TRACE_LOADED_OBJECTS=1 ./exec/1-1.out
其次,您几乎不应该在shell脚本中使用$*
。请改用“$@”(注意:引号很重要)。看这个
第三,你观察到的行为很容易解释。要理解它,您需要知道所描述的DT_RPATH
和DT_RUNPATH
之间的区别
您可以验证二进制文件当前是否正在使用运行路径,如下所示:
readelf -d 1-1.out | grep 'R.*PATH'
您可以通过向link命令添加-Wl,--disable new dtags
(这将导致二进制文件改用RPATH
)来验证一切是否按预期开始工作
总结如下:
影响对二进制文件本身的搜索,但不影响对二进制文件所依赖的任何库的搜索RUNPATH
影响二进制文件及其所依赖的所有库的搜索路径RPATH
- 使用
,仅当二进制文件直接依赖于它时,才会找到预期的运行路径
,但当对libpthread.so.0
的依赖是间接的(通过libpthread
)时,则不会找到该文件librt
- 使用
,无论依赖关系是直接的还是间接的,都会找到预期的RPATH
libpthread.so.0
-rpath=${SYSROOT}/lib64
链接librt.so
您可以编辑rt/Makefile
,或使用以下内容生成:
make LDFLAGS-rt.so='-Wl,--enable-new-dtags,-z,nodelete,-rpath=${SYSROOT}/lib64'
对于可能对GLIBC的其他部分产生可传递依赖性的任何其他库,您都需要这样做。我不知道有什么通用的方法可以做到这一点,但是通过设置
LDFLAGS lib.so='-Wl,-rpath=${SYSROOT}/lib64'
,然后重建所有的东西就可以了。“此外,…/dobuild 1-1.c-lrt-pthread
,ldd结果显示所有依赖的库都指向安装的glibc。”--生成的二进制文件是否有效?@EmployedRussian是的,工作成功!感谢您的评论“此外…/dobuild 1-1.c-lrt-pthread