制作共享对象时,不能使用针对“.bss”段的重定位R_X86_64_32S。

6

我对此完全不了解,但在课堂上,老师给我们提供了一个文件,供我们运行。当时它可以正常工作,但回到家后(我使用VirtualBox中的Linux),我尝试运行它,使用以下命令:

nasm -f elf64 hello.asm -o hello.o
gcc hello.o -o hello

我遇到了一个错误:“在制作共享对象时不能使用重定位R_X86_64_32S,因为它针对`.bss';请使用-fPIC重新编译”。请问有人能解释一下如何使其正常工作吗?
global main
extern printf

section .data
napis:      db ' Hello world! - po raz %ld',10,0

liczba_iteracji: equ 5

section .bss
licznik: resb 1

section .text

main:

push    rbp
mov rbp,rsp

mov byte [licznik],0

petla:              ;naiwna!

inc byte [licznik]

mov rdi, qword napis
mov rsi, qword [licznik]
mov rax, 0
call    printf

cmp byte [licznik],liczba_iteracji
jnz petla

mov rsp,rbp
pop rbp

mov rax,1           ;SYS_EXIT
mov rbx,0
int 80h

1
可能是What do R_X86_64_32S and R_X86_64_64 relocation mean?的重复问题。 - Michael Foukarakis
1
使用gcc -shared -fPIC foo.c -o libfoo.so的答案并没有解决我的问题。 - overflow
2个回答

3
我遇到了同样的问题。GCC报错的原因是它假设(在这里是6.3.0版本)你正在构建共享对象(但很明显你不是),因此.bss的存在使它变得疯狂。因此,你可以通过传递-static选项来修复这个问题:gcc hello.o -static -o hello(在我的情况下有效),或者使用Clang作为链接器:clang hello.o -o hello。后者没有任何抱怨。

PIE可执行文件实际上是ELF共享对象。在x86-64 Linux中不再允许32位绝对地址吗?更好的解决方法是尽可能避免使用32位绝对寻址,可以通过使用“default rel”或者使用“-fno-pie -no-pie”来提高代码的效率。 - Peter Cordes

2
你需要确保你正在编写位置无关代码。PIC的想法是,为了使代码真正成为位置无关的,你至少需要一层间接寻址。这种间接寻址是IP相对寻址,当这还不够时,你将需要第二层,全局偏移表或GOT。
在NASM中,你会发现DEFAULT REL指令非常有用。

PIE可执行文件不需要通过GOT间接访问自己的函数/变量;这只是为了支持符号重定位。gcc -fPIC意味着共享库符号重定位,但现代默认的gcc -fpie -pie只需要避免32位绝对寻址。所以是的,“default rel”。x86-64 Linux不再允许32位绝对地址吗? - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接