制作共享对象时不能使用针对 .data 的重定位 R_X86_64_32S(64 位 NASM + gcc)

2023-12-30

我正在尝试使用 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

I get:

/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 https://stackoverflow.com/questions/33476098/gcc-assemby-error-relocation-r-x86-64-32s-against-data and this https://www.csee.umbc.edu/portal/help/nasm/sample_64.shtml#fib_64m.asm。我找不到任何实际的文档explains不过,出于某种原因(事实上,我几乎找不到任何关于使用 NASM 进行 64 位开发的有用文档,这使得我迄今为止所做的一切都变得非常痛苦),并添加类似的事情对我的错误输出没有任何影响。

Update:

我一直在看this http://www.nasm.us/doc/nasmdo11.html and this https://stackoverflow.com/questions/48071280/nasm-symbol-printf-causes-overflow-in-r-x86-64-pc32-relocation.

如果我将 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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

制作共享对象时不能使用针对 .data 的重定位 R_X86_64_32S(64 位 NASM + gcc) 的相关文章

随机推荐