含递归函数的.so库编译失败:R_X86_64_PC32重定位错误排查
解决共享库构建时的R_X86_64_PC32重定位错误(递归函数场景)
嘿,我之前在项目里也碰到过完全一样的问题!当时折腾了好一会儿才搞明白,尤其是手写汇编实现递归函数的时候,这个错误特别容易找上门。
先给直接解决方案
你看到的错误提示其实已经点出了核心修复方向:recompile with -fPIC。不过因为你是手写汇编代码,不是依赖C/C++编译器自动生成,所以得手动在汇编里处理位置无关的寻址逻辑。
对于x86_64架构的共享库,所有函数调用、内存引用都必须采用位置无关的方式——这是因为共享库会被加载到进程地址空间的任意位置,位置相关的代码会导致重定位失败。
为什么递归函数会触发这个错误?
你的原始汇编代码里,递归调用factorial时用的是直接符号引用/相对跳转,这种代码属于**位置相关(non-PIC)**类型。而共享库要求代码能在任意地址正常执行,必须用特殊的寻址方式(比如通过全局偏移表GOT)来间接引用函数地址,递归调用自然也得遵循这个规则。
修改后的PIC兼容汇编示例
把你的递归阶乘函数改成符合共享库要求的版本:
.section .text .globl factorial .type factorial, STT_FUNC factorial: push %rbp mov %rsp, %rbp mov 16(%rbp), %rax cmp $1, %rax je end_factorial # 递归调用改为PIC兼容的寻址方式 dec %rax push %rax call *factorial@GOTPCREL(%rip) # 通过GOT间接引用函数地址 pop %rdi imul 16(%rbp), %rax end_factorial: pop %rbp ret
配套编译命令
编译这个汇编文件生成共享库时,记得加上-fPIC参数(汇编器和链接器都会用到):
as -fPIC -o factorial.o factorial.s gcc -shared -o libfactorial.so factorial.o
简单解释下关键修改:factorial@GOTPCREL(%rip)是x86_64架构下PIC代码引用函数符号的标准写法,它通过指令指针%rip的相对偏移访问全局偏移表(GOT)中的函数地址,确保不管库被加载到哪个内存位置,都能正确找到递归函数的入口。
如果是用C写的递归函数,只需要编译时加-fPIC,编译器会自动处理这些细节,但手写汇编就得自己搞定这些寻址逻辑啦!
内容的提问来源于stack exchange,提问作者Andrew Bolotov
相关产品推荐
相关产品推荐

