问题现象:
如下代码:
//file name: test.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("hello world\n");
exit(0);
}
对其执行:
gcc -S test.c
as -o test.o test.s
ld -o test -e main -lc test.o
生成可执行文件test,运行可执行文件结果报错如下:
alex@ubuntu:~/assembly/charpter1$ ./test
bash: ./test: No such file or directory
排查步骤
- 使用gcc编译直接生成可执行文件a.out。执行步骤如下:
gcc test.c
生成a.out可执行,运行结果如下:alex@ubuntu:~/assembly/charpter1$ ./a.out hello world
排除编码原因导致的不可执行
- 使用ldd 命令排查两个可执行文件链接到的动态库是否一致:
1). ldd -v test查询test可执行文件链接的动态库
alex@ubuntu:~/assembly/charpter1$ ldd -v test
linux-gate.so.1 => (0xb77b9000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75f3000)
/usr/lib/libc.so.1 => /lib/ld-linux.so.2 (0xb77ba000)
Version information:
./test:
libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
/lib/i386-linux-gnu/libc.so.6:
ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
2).ldd -v a.out查询a.out可执行文件链接的动态库:
alex@ubuntu:~/assembly/charpter1$ ldd -v a.out
linux-gate.so.1 => (0xb77b0000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75ea000)
/lib/ld-linux.so.2 (0xb77b1000)
Version information:
./a.out:
libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
/lib/i386-linux-gnu/libc.so.6:
ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
发现test可执行文件和a.out可执行文件动态链接库总体差不多,细节上有区别,最大区别在于test可执行文件动态连接到:/usr/lib/libc.so.1 => /lib/ld-linux.so.2 (0xb77ba000)
。
查询/usr/lib/libc.so.1发现文件不存在,可以大体上确定./test执行错误的原因在于此。
验证
- 生成一个软连接文件:
sudo ln -s /lib/ld-linux.so.2 /usr/lib/libc.so.1
再执行可执行文件./test执行成功,如下:
alex@ubuntu:~/assembly/charpter1$ ./test
hello world
- 删除软连接文件,报如上错误:
alex@ubuntu:~/assembly/charpter1$ ./test
bash: ./test: No such file or directory
问题根因
ld在链接过程中默认链接的是/usr/lib/libc.so.1文件,而这个文件在ubuntu 14.04中是不存在的。增加这个文件可以解决动态库链接失败的问题。
根本解决方案
可执行文件最终链接到/lib/ld-linux.so.2文件,可以在链接步骤增加动态库链接步骤,如下:
ld -o test -e main -ld ./test.o -dynamic-linker /lib/ld-linux.so.2