【问题标题】:Relocation R_X86_64_32S against .data cannot be used when making a shared object (64 bit NASM + gcc)制作共享对象时不能使用针对 .data 的重定位 R_X86_64_32S(64 位 NASM + gcc)
【发布时间】:2018-06-19 17:16:08
【问题描述】:

我正在尝试使用 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 等示例中存在奇怪的堆栈操作来看,我感觉我做错了一些事情。但是,出于某种原因,我找不到任何实际解释的文档(事实上,我几乎找不到任何有用的文档,一般来说,使用 NASM 进行 64 位开发,这使我所做的一切' 到目前为止真的很痛苦),并且添加类似的东西对我的错误输出没有任何影响。

更新:

我一直在看thisthis

如果我将主要更改为:

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

  ret

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

【问题讨论】:

标签: c linux assembly nasm libc


【解决方案1】:

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

【讨论】:

  • 太好了,它有效!请问你是从哪里学来的?我一直在努力寻找一个使用 libc 的 64 位 NASM 的好指南。
  • call [puts wrt ..got] 也是正确的;它是gcc -fno-plt code-gen 的 NASM 等价物。 Can't call C standard library function on 64-bit Linux from assembly (yasm) code 显示了这两个选项,通过 GOT 内联间接调用或仅调用 PLT 存根。 (@EthanMcTague)
猜你喜欢
  • 2020-01-26
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 2018-09-01
  • 2016-06-06
  • 1970-01-01
  • 2018-08-12
相关资源
最近更新 更多