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

汇编编写共享对象跨文件调用符号时ld报R_X86_64_PC32错误,如何解决?

解决x86_64汇编共享对象的R_X86_64_PC32重定位错误

这个错误的核心原因很明确:x86_64架构下的共享对象(.so文件)必须是位置无关代码(PIC),而你当前的编译/链接流程没有生成符合要求的代码。R_X86_64_PC32是一种针对固定地址的重定位类型,无法用于加载地址不固定的共享对象,所以我们需要调整汇编代码和编译链接选项来解决。

第一步:调整汇编代码的调用方式

当你在第二个文件中调用第一个文件的符号(比如strchr)时,不能直接用普通的call strchr,而要通过**过程链接表(PLT)**来调用,这是PIC代码的要求。修改调用语句为:

call strchr wrt ..plt

同时,确保在定义strchr的第一个ASM文件中,用global声明该符号为全局可导出:

global strchr

在调用它的第二个文件中,用extern声明该符号:

extern strchr

第二步:编译生成PIC兼容的目标文件

使用NASM编译每个ASM文件时,必须加上-PIC选项来生成位置无关代码,同时指定64位ELF格式:

nasm -f elf64 -PIC file1.asm -o file1.o
nasm -f elf64 -PIC file2.asm -o file2.o

-f elf64确保生成x86_64架构的目标文件,-PIC让NASM生成不依赖固定加载地址的代码,所有内存访问和函数调用都会采用相对寻址或通过GOT/PLT表实现。

第三步:链接生成共享对象

用ld链接时,加上-shared选项明确告诉链接器要生成共享对象,而不是可执行文件:

ld -shared -o libyourlib.so file1.o file2.o

如果需要指定共享对象的soname(可选,但推荐),可以加上-soname libyourlib.so.1这样的选项,方便后续版本管理。

示例完整流程

假设我们有两个文件:

file1.asm(定义strchr)

global strchr

section .text
strchr:
    mov rax, rdi                ; 把字符串起始地址存入rax
.loop:
    cmp byte [rax], sil         ; 比较当前字符和目标字符
    je .found                   ; 找到就返回当前地址
    cmp byte [rax], 0           ; 遇到字符串结尾就返回空
    je .not_found
    inc rax                     ; 否则移动到下一个字符
    jmp .loop
.found:
    ret
.not_found:
    mov rax, 0
    ret

file2.asm(调用strchr)

extern strchr
global find_a_char

section .text
find_a_char:
    ; 示例:调用strchr查找字符串中的'a'
    mov rdi, rsi                ; 第一个参数:传入的字符串
    mov sil, 'a'                ; 第二个参数:要查找的字符
    call strchr wrt ..plt       ; 通过PLT调用strchr
    ret

编译链接命令:

nasm -f elf64 -PIC file1.asm -o file1.o
nasm -f elf64 -PIC file2.asm -o file2.o
ld -shared -o libmystr.so file1.o file2.o

这样生成的libmystr.so就是符合要求的共享对象,不会再出现R_X86_64_PC32的重定位错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:58:06