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

时间:2018-01-10 13:57:12

标签: c linux assembly nasm libc

我试图用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

我有一种感觉,我做错了一些事情,从thisthis等例子中存在奇怪的堆栈操作来判断。由于某种原因,我无法找到任何实际解释的文档(事实上,我很难找到任何有用的文档来进行64位一般的NASM开发,这已经做了到目前为止,我所做的一切都是屁股的真正痛苦),并添加这样的东西对我的错误输出没有任何影响。

更新

我一直在关注thisthis

如果我将主要内容更改为:

  push rbp
  mov rax,0
  mov rdi, hi
  call [puts wrt ..got]
  pop rbp
  mov rax,0

  ret

它编译得很好,但是在运行而不是实际打印时会给我一个段错误。我也不明白为什么我要从堆栈中推送rbp的价值,以及为什么rax的价值在这种情况下很重要。

1 个答案:

答案 0 :(得分:2)

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