You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写x86-64汇编版write函数时,链接PIE目标文件遇到__errno_location重定位错误

编写x86-64汇编版write函数时,链接PIE目标文件遇到__errno_location重定位错误

嘿,我刚好碰到过类似的问题,这事儿的根源在于NASM和GCC默认的编译模式不匹配,咱们一步步来解决:

问题本质

GCC现在默认会把代码编译链接成PIE(位置无关可执行文件),但NASM默认生成的是非位置无关的目标文件。当你调用__errno_location时,NASM默认用了R_X86_64_PC32这种重定位类型,而这种类型在PIE对象里是不允许的,所以链接器就报错了。

解决方案(两种可选)

方案1:让NASM直接生成PIE兼容的目标文件

从NASM 2.13版本开始,官方支持了生成PIE目标文件的选项,你只需要修改汇编命令:

nasm -f elf64 -pie -o my_write.o my_write.s

之后再用原来的GCC命令链接:

gcc -o test main.c my_write.o

这样就能正常编译链接了,不需要改汇编代码。

方案2:手动修改汇编代码,适配PIE模式

如果你的NASM版本比较老,不支持-pie选项,那可以修改汇编里调用__errno_location的方式,用PIE兼容的位置无关寻址:
把原来的call __errno_location改成:

call __errno_location WRT ..plt

或者用rip相对寻址的写法:

lea rax, [rel __errno_location]
call [rax]

这两种写法都会让NASM生成PLT(过程链接表)相关的重定位,完全兼容PIE模式。修改完汇编代码后,还是用原来的汇编命令:

nasm -f elf64 -o my_write.o my_write.s

再进行链接就没问题了。

验证一下

你可以测试下错误场景,比如给my_write传一个无效的文件描述符(比如-1),然后打印errno看看是否正确设置:

// 在main.c里加一段测试代码
if (my_write(-1, str, 5) == -1) {
    printf("errno: %d, error msg: %s\n", errno, strerror(errno));
}

运行后应该能看到正确的错误码(比如EBADF,对应数值9),说明你的汇编代码里设置errno的逻辑是正常的。

备注:内容来源于stack exchange,提问作者Fartomy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 08:44:30