我正在尝试跟进这个线程,但不幸的是它并没有完全解决我的问题。我要运行的代码如下:
; File hello.asm
section .data
msg: db "Hello World!",0x0a,0
section .text
global main
extern printf
main:
push rbp
mov rbp, rsp
lea rdi, [msg] ; parameter 1 for printf
xor eax, eax ; 0 floating point parameter
call printf
xor eax, eax ; returns 0
pop rbp
ret
我的系统是Debian Stretch:
$ uname -a
Linux <host> 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux
我正在使用 yasm
汇编器,如下所示:
$ yasm -f elf64 -g dwarf2 hello.asm
由于我在上文中的入口点是带有最终指令 ret
的main
,我猜想我需要与gcc
链接而不是ld -e main
:
$ gcc -lc hello.o
然而,我收到了以下错误信息:
/usr/bin/ld: hello.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
这个错误提到需要使用
-fPIC
重新编译,但这是gcc
编译器选项,不是汇编器yasm
的有效选项。所以我不知道该怎么办。为了测试,我试图链接
ld
:$ ld -e main -lc hello.o
这个操作是成功的,但是当我运行以下命令时,我遇到了与上面提到的线程中相同的错误:
$ ./a.out
bash: ./a.out: No such file or directory # The file *is* there ...
(根据帖子的答案,我已经尝试比较
ld
二进制文件中提到的.so
库与我的系统库,它们都是/lib64/ld-linux-x86-64.so.2
。)我也尝试将main
入口点替换为_start
(暂时忘记程序正确退出的问题),并链接ld -lc hello.o
,但我得到了与之前相同的“没有这样的文件或目录”的错误消息。虽然我会继续尝试,但我还是想问一下有没有有效建议(包括使用main
或_start
,以及gcc
或ld
)。如果您有任何有效建议,请告诉我。
编辑:如Jim所建议的,我在hello.asm
顶部添加了default rel
,并在使用gcc链接时获得不同的错误消息(使用ld -e main -lc
没有变化)。$ gcc -lc hello.o
/usr/bin/ld: hello.o: relocation R_X86_64_PC32 against symbol `printf@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
编辑2:本文与Debian Stretch
上的失败有关:
Linux: 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux
yasm: 1.3.0
gcc: (Debian 6.2.1-5) 6.2.1 20161124
ld: GNU ld (GNU Binutils for Debian) 2.27.51.20161220
在Jim的评论后,我刚刚在debian jessie
上测试了相同的代码,使用gcc -lc hello.o
和以下版本,一切正常:
Linux: 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux
yasm: 1.2.0
gcc: (Debian 4.9.2-10) 4.9.2
ld: GNU ld (GNU Binutils for Debian) 2.25
编辑3: 在等待迈克尔·佩奇的正式回答时:问题已解决方法是 gcc -static hello.o
hello.o
的重定位类型有关。我建议在hello.asm
的顶部添加指令default rel
,看看是否可以解决问题或提供不同的错误信息。你是故意尝试使用R_X86_64_32重定位吗? - JimD.gcc -static hello.o
静态构建,会发生什么? - Michael Petchgcc -lc -static hello.o
在debian stretch
机器上完美运行。顺便提一下,在debian jessie
上也可以运行。如果你想写一个答案,我很乐意验证它。如果你有任何关于可能发生的事情的见解,也非常欢迎(但我不想占用你太多时间)。非常感谢!!! - Sven Williamsongcc
时,-lc
选项是不必要的(我也是从ld
养成这个习惯)。然而,无论是否在hello.asm
的顶部加上default rel
,gcc hello.o
都会导致相同的错误,而gcc -static hello.o
则成功。 - Sven Williamson