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

ARM64位置无关汇编全局变量访问问题:函数迁移后失效如何解决?

macOS ARM64汇编迁移内存后正确访问全局变量的方案

问题根源

你遇到的问题本质是PC相对寻址的局限性:adrp/ldr(或汇编优化后的adrp/add)是基于当前指令的PC值计算全局变量地址的。当你把函数用memcpy复制到其他内存位置后,PC的基准位置完全改变,原来预计算的相对偏移自然失效,导致全局变量地址加载错误。

正确解决方法

1. 通过全局偏移表(GOT)间接访问

GOT是进程启动时被系统填充的地址表,其中存储着全局变量的绝对地址,与函数的运行位置无关。使用GOT访问的汇编代码示例:

; 获取全局变量在GOT中的条目地址
adrp    x0, _global_var@GOTPAGE
ldr     x0, [x0, _global_var@GOTPAGEOFF]
; 从GOT条目中读取全局变量的绝对地址
ldr     x0, [x0]
; 此时x0中就是_global_var的正确地址,可直接读写

不管函数被迁移到内存的哪个位置,只要GOT的位置不变(进程生命周期内固定),就能正确拿到全局变量地址。

2. 基于静态基址(SB)寻址

对于小数据全局变量(通常是数据段中的小变量),可以使用静态基址寻址,它依赖的是程序静态段的基址而非当前函数的PC:

adrp    x0, _global_var@SB
add     x0, x0, _global_var@SBOFF
; x0即为_global_var的地址

这种方式同样不受函数迁移的影响,因为静态段基址在进程启动后固定(即使开启ASLR,也是整个静态段偏移,相对关系不变)。

3. 编译时生成位置无关代码

如果你用Clang编译汇编代码,务必添加-fpic或-fPIC选项,强制编译器生成位置无关的代码逻辑,自动处理全局变量的寻址问题,避免手动编写PC相对的寻址指令。

补充说明

你看到ldr被汇编成add是汇编器的正常优化:当全局变量的页内偏移为0时,ldr [x0, #0]等价于直接把x0的值作为地址,汇编器会优化为add x0, x0, #0(或直接保留x0),但这不会改变PC相对寻址的本质,所以迁移后依然出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:20:37