【发布时间】:2018-02-17 19:04:43
【问题描述】:
这是一个从未发生过的问题。我非常确信这可能是我的软件包存储库的问题(我最近重新安装了我的 Arch 系统,而这才刚刚开始发生)。
我在x86_64中写了一个小小的hello world:
.data
str: .asciz "Test"
.text
.globl main
main:
sub $8, %rsp
mov $str, %rdi
call puts
add $8, %rsp
ret
然后我尝试使用 GCC 进行组装和链接 - 就像我过去做过很多次一样 - 简单地说:
gcc test.s -o 测试
然后输出这个错误:
/usr/bin/ld: /tmp/ccAKVV4D.o: 重定位 R_X86_64_32S 对 `.data' 在制作共享对象时不能使用;使用 -fPIC 重新编译 /usr/bin/ld:最终链接失败:输出中不可表示的部分 collect2:错误:ld 返回 1 个退出状态
我从来没有发生过这个错误。我试图通过谷歌搜索相同的错误消息来解决这个问题,但它提出了一些非常具体的问题,而我认为这是一个普遍的问题。我尝试重新安装 base-devel 和整个 GCC 工具链。我不知道我还能做什么(请不要建议使用 nasm,那是异端)。
我想我遗漏了一些明显的东西,但我长期以来一直使用 GCC 来满足我的装配需求。
【问题讨论】:
-
我有点确定这是重复的,但我稍后会搜索它,所以简单总结一下发生了什么。 Debian 前段时间确实在 64b 模式下切换到 PIC/PIE 二进制文件(就像 OS X 已经有一段时间了,现在其他发行版也随之而来),因此修改了工具链的默认值,在你的情况下
gcc是试图将您的对象链接为 PIC,但它会在mov $str, %rdi中遇到绝对地址。因此,您要么应该将代码重写为rip在任何地方都是相对的,要么可能有一些方法可以设置 gcc 链接以强制执行旧的非 PIC 链接。 -
感谢@Ped7g 的洞察力,我会调查一下
-
您可能正在使用更新/不同版本的 Arch Linux,它默认将 GCC 构建为可重定位的 64 位代码。处理此问题的最佳方法是修改您的代码以使用 RIP(相对指令指针)寻址。将您的
mov更改为lea str(%rip), %rdi并在调用 C 库时使用call puts@plt而不是call puts。 -
使用
no-pie标志编译。那是gcc -no-pie test.s -o test。这必须有效,因为它不会生成共享对象,而是生成可执行文件。我在我的本地机器上尝试过它并且它工作但仍然不知道为什么。 @oldjohn1994 -
@MichaelPetch 谢谢,我只是想问一下如何在相关代码中使用 libc 函数。为此干杯。
标签: gcc assembly gnu-assembler