ARMv7下Clang编译含LDR reg,=symbol的汇编生成共享库链接失败
解决ARMv7 FreeBSD下clang-16编译汇编代码生成共享库的R_ARM_ABS32重定位错误
问题原因
clang-16的ARM集成汇编器对PIC(位置无关代码)的处理逻辑与GNU汇编器(GAS)存在差异:LDR r12, =g_lumaFilter这类伪指令在PIC模式下,clang会生成R_ARM_ABS32类型的绝对重定位,而共享库不允许针对局部符号使用这种重定位;但GAS会自动将其转换为PC相对寻址或兼容PIC的GOT表访问方式,因此g++编译链接正常。
解决方案
方案1:强制clang使用GNU汇编器编译.S文件
直接让clang调用系统的GAS处理汇编代码,对齐g++的编译行为,无需修改汇编源码:
- 编译汇编文件时添加
-no-integrated-as参数:clang-16 -c -fPIC -no-integrated-as your_arm_asm.S -o your_arm_asm.o - 链接生成共享库时正常执行:
clang-16 -shared -o libx265.so *.o
方案2:修改汇编代码为PIC兼容的寻址方式
如果需要使用clang的集成汇编器,将绝对加载伪指令替换为基于GOT表的PC相对寻址:
.global g_lumaFilter .type g_lumaFilter, %object g_lumaFilter: ; 符号定义内容 ; 替换原有的 LDR r12, =g_lumaFilter LDR r12, =__GLOBAL_OFFSET_TABLE__ ADD r12, pc, r12 ; 计算GOT表的PC相对地址 LDR r12, [r12, #:got_lo12:g_lumaFilter] ; 从GOT表中加载符号地址
这种方式通过全局偏移表(GOT)间接访问符号,符合PIC规范,clang汇编器会生成合法的重定位类型。
方案3:完善符号声明属性
确保汇编中的全局符号明确声明类型,帮助clang正确识别符号属性:
.global g_lumaFilter .type g_lumaFilter, %object ; 声明为对象类型,若为函数则用%function g_lumaFilter: ; 符号内容
内容的提问来源于stack exchange,提问作者Mikhail T.
相关产品推荐
相关产品推荐

