使用 GCC 组装会导致 .data 出现奇怪的重定位错误
Posted
技术标签:
【中文标题】使用 GCC 组装会导致 .data 出现奇怪的重定位错误【英文标题】:Assembling with GCC causes weird relocation error with regards to .data 【发布时间】: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 函数。为此干杯。
【参考方案1】:
解决这个错误的方法是生成一个no-pie
(非位置无关的可执行文件)可执行文件:
gcc -no-pie test.s -o test
@Ped7g 解释了这种行为的原因:
Debian 切换到 64 位模式下的 PIC/PIE 二进制文件,在您的情况下,GCC 正在尝试将您的对象链接为 PIC,但它会在mov $str, %rdi
中遇到绝对地址。
【讨论】:
他在这种情况下使用 Arch,但同样适用于 Debian。字符串的地址不是唯一的问题。 C 库的调用也必须修改。 @MichaelPetch:-no-pie
修复一切,并将call puts
转换为call puts@plt
为您服务。如果您希望它在 PIE 中工作,您只需要修改 call
指令。具体来说,call *puts@GOTPCREL(%rip)
如果使用gcc -fno-plt
构建(非延迟动态链接以避免可写+可执行PLT,并避免额外间接),或者call puts@PLT
用于默认方式。 (或者 call puts@plt
也可以。编译器在编译 C 时会发出大写的 PLT。)
相关:32-bit absolute addresses no longer allowed in x86-64 Linux? 有同样的答案。顺便说一句,movabs $str, %rdi
将在 PIE 可执行文件中工作;允许文本重定位,但不允许 32 位 符号或零扩展重定位。但不要那样做,对 PIC 使用相对于 RIP 的 LEA,或者对位置相关使用 mov $str, %edi
。以上是关于使用 GCC 组装会导致 .data 出现奇怪的重定位错误的主要内容,如果未能解决你的问题,请参考以下文章
混合 Spring MVC + Spring Data Rest 会导致奇怪的 MVC 响应
Spring 4 Security + CORS + AngularJS - 奇怪的重定向