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

NASM编写x64共享库遇R_X86_64_PC32重定位错误求助

解决NASM x64编译共享库的R_X86_64_PC32重定位错误

问题本质:NASM的PIC写法和GCC不兼容

你提到已经启用了PIC选项,但NASM生成位置无关代码的逻辑和GCC的-fPIC完全不同。x64共享库要求所有符号引用必须使用位置无关寻址方式,R_X86_64_PC32错误就是因为你的代码里用了绝对地址引用,不符合PIC规范——当前这个错误和GLIBC函数名冲突无关,但重名确实可能埋下后续隐患,可以后续排查。

修正PIC兼容的函数调用方式

如果你的putstr里调用strlen是直接写call strlen,必须改成PIC兼容的PLT调用格式:

call strlen wrt ..plt

要是代码里有引用全局数据,也得换成rip-relative寻址,比如[rip+my_data],不能直接使用绝对地址。

符号冲突的排查方法

虽然当前错误不是冲突导致,但重名可能引发隐式依赖:

  • 编译完目标文件后用nm strlen.o查看符号表,确认strlen是T(文本段,已定义)而非U(未定义),确保你的实现被正确导出。
  • 链接时添加-z defs参数,强制链接器检查未定义符号,这样如果不小心引用了GLIBC的同名函数,会直接报错,方便定位问题。

正确的Makefile配置示例

确保NASM编译用-f elf64,链接用ld -shared,并加上必要的参数:

NASM_FLAGS := -f elf64
LDFLAGS := -shared -z noexecstack -z defs

minilibc.so: strlen.o putstr.o
	ld $(LDFLAGS) -o $@ $^

strlen.o: strlen.asm
	nasm $(NASM_FLAGS) -o $@ $<

putstr.o: putstr.asm
	nasm $(NASM_FLAGS) -o $@ $<

注意:NASM的-DPIC只是定义一个宏,真正的PIC逻辑需要在汇编代码里手动实现(比如用wrt ..plt调用函数)。

额外注意事项

  • 如果putstr需要输出内容,别依赖GLIBC的write函数,直接写x64系统调用汇编,彻底避免和GLIBC的依赖:
    ; x64 Linux下的write系统调用示例
    mov rax, 1          ; syscall编号:write
    mov rdi, 1          ; 文件描述符:stdout
    mov rsi, buffer     ; 要输出的缓冲区地址
    mov rdx, len        ; 输出长度
    syscall
    
  • 用readelf -r minilibc.so查看重定位表,正常情况下应该只有R_X86_64_PLT32或R_X86_64_GOTPCREL类型的重定位项,没有R_X86_64_PC32。

内容的提问来源于stack exchange,提问作者Nayrosk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:52:42