编写x86_64汇编共享对象时如何处理R_X86_64_PC32重定位错误
解决x86_64共享对象中受保护符号的R_X86_64_PC32重定位错误
直接在汇编源码中添加.note.gnu.property节并设置GNU_PROPERTY_NO_COPY_ON_PROTECTED属性,即可解决链接错误。以下是完整的可运行汇编代码示例:
# 定义GNU属性节,设置NO_COPY_ON_PROTECTED .section .note.gnu.property,"a" .align 8 .long 4 # 名称长度("GNU"的字节数) .long 0x10 # 描述数据长度(后续4个long的总字节数) .long 5 # Note类型:GNU_PROPERTY_TYPE_0 .asciz "GNU" # 属性名称 .long 0xc0000000 # 属性掩码:GNU_PROPERTY_NO_COPY_ON_PROTECTED .long 4 # 数据大小 .long 0 # 保留字段 # 数据段:受保护的全局符号g .section .data .protected g .globl g g: .quad 0xdeadbeef # 代码段:引用g的函数f .section .text .globl f .type f, @function f: # RIP相对寻址访问g movq g(%rip), %rax ret
关键部分说明
- .note.gnu.property节:这是GNU工具链专属的ELF note节,用于向链接器传递目标文件属性。节属性
"a"表示该节会被分配到输出文件中。- 属性值
0xc0000000对应GNU_PROPERTY_NO_COPY_ON_PROTECTED(第30位为1),告诉链接器不对受保护符号启用copy-on-write机制,从而允许使用R_X86_64_PC32重定位。
- 属性值
- 符号声明顺序:必须先写
.protected g再声明.globl g,确保符号的受保护属性被正确标记。 - RIP相对寻址:
g(%rip)是x86_64下访问全局符号的标准RIP相对方式,会生成R_X86_64_PC32重定位,现在能被链接器正常处理。
编译验证
使用GNU工具链编译链接:
as -o test.o test.s ld -shared -o libtest.so test.o
链接过程不会再出现重定位R_X86_64_PC32无法用于受保护符号g的错误。可以通过以下命令确认属性和符号:
readelf -n libtest.so:查看.note.gnu.property节的属性设置objdump -x libtest.so | grep g:确认g的符号属性为PROTECTED
内容的提问来源于stack exchange,提问作者Marc
相关产品推荐
相关产品推荐

