创建共享对象时不能使用针对 .data 的重定位 R_X86_64_32S(64 位 NASM + gcc)
Relocation R_X86_64_32S against .data cannot be used when making a shared object (64 bit NASM + gcc)
我正在尝试使用 NASM 和 GCC 编写程序:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push hi
call puts
ret
我正在构建:
nasm -f elf64 main.asm
gcc main.o -o main
rm main.o
我得到:
/usr/bin/ld: main.o: relocation R_X86_64_32S 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
从 and this 等示例中存在奇怪的堆栈操作来判断,我感觉自己做错了几件事。不过,出于某种原因,我找不到任何实际 解释 的文档(事实上,我几乎找不到任何使用 NASM 进行 64 位开发的有用文档general,这让我到目前为止所做的一切都变得非常痛苦),并且添加类似的东西对我的错误输出没有任何影响。
更新:
我一直在看 this and this。
如果我将 main 更改为:
push rbp
mov rax,0
mov rdi, hi
call [puts wrt ..got]
pop rbp
mov rax,0
ret
它编译得很好,但是当 运行 而不是实际打印时给我一个段错误。我也不明白为什么我要从堆栈中推入和拉出 rbp
的值,以及为什么 rax
的值在这种情况下很重要。
rbp
是一个被调用者保存的寄存器,因此您需要保留它。您没有更改它,因此您不必在此处 push
/pop
它。但是,您需要保留 16 字节堆栈对齐,push
是一种简单的方法。您可以使用任何其他寄存器,甚至 sub rsp, 8
.
mov rdi, hi
应该是 lea rdi, [rel hi]
.
函数是通过 PLT 而非 GOT 调用的,也不是通过指针调用的。就做 call puts ..wrt plt
.
因此,以下应该有效:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push rbp
lea rdi, [rel hi]
call puts wrt ..plt
pop rbp
ret
我正在尝试使用 NASM 和 GCC 编写程序:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push hi
call puts
ret
我正在构建:
nasm -f elf64 main.asm
gcc main.o -o main
rm main.o
我得到:
/usr/bin/ld: main.o: relocation R_X86_64_32S 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
从
更新:
我一直在看 this and this。
如果我将 main 更改为:
push rbp
mov rax,0
mov rdi, hi
call [puts wrt ..got]
pop rbp
mov rax,0
ret
它编译得很好,但是当 运行 而不是实际打印时给我一个段错误。我也不明白为什么我要从堆栈中推入和拉出 rbp
的值,以及为什么 rax
的值在这种情况下很重要。
rbp
是一个被调用者保存的寄存器,因此您需要保留它。您没有更改它,因此您不必在此处 push
/pop
它。但是,您需要保留 16 字节堆栈对齐,push
是一种简单的方法。您可以使用任何其他寄存器,甚至 sub rsp, 8
.
mov rdi, hi
应该是 lea rdi, [rel hi]
.
函数是通过 PLT 而非 GOT 调用的,也不是通过指针调用的。就做 call puts ..wrt plt
.
因此,以下应该有效:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push rbp
lea rdi, [rel hi]
call puts wrt ..plt
pop rbp
ret