解决ld可以链接并且生成可执行文件但是执行不了可执行文件问题

问题现象:

如下代码:

//file name: test.c
#include 
#include 
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

排查步骤

  1. 使用gcc编译直接生成可执行文件a.out。执行步骤如下:
    gcc test.c
    生成a.out可执行,运行结果如下:
    alex@ubuntu:~/assembly/charpter1$ ./a.out 
    hello world
    

排除编码原因导致的不可执行

  1. 使用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执行错误的原因在于此。

验证

  1. 生成一个软连接文件:
sudo ln -s /lib/ld-linux.so.2 /usr/lib/libc.so.1

再执行可执行文件./test执行成功,如下:

alex@ubuntu:~/assembly/charpter1$ ./test 
hello world
  1. 删除软连接文件,报如上错误:
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

你可能感兴趣的:(编译)