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

ARM Mac汇编:Linux跨平台编译GOT段加载异常问题

问题背景

现有一段ARM64汇编代码可在macOS正常编译运行,但在Linux环境下编译时会提示找不到_write符号。代码中svc指令后的bl _write语句移除后程序运行崩溃。用户尝试通过dump stub和GOT段并嵌入汇编的方式解决,但GOT段始终无法被更新为有效函数指针,动态链接失效。核心需求:

  • 不依赖_write等macOS动态库符号实现程序正常加载运行
  • 或在无macOS库/dylib的Linux环境下完成编译,同时能使用malloc/free/realloc等高效动态函数(以write为测试用例)
  • 编译出的程序需能在macOS正常运行,优先保留动态库函数调用能力而非直接使用系统调用

方案1:直接使用macOS系统调用替代动态库函数

macOS ARM64架构下,系统调用通过svc #0触发,寄存器约定明确:

  • x16:存储系统调用编号
  • x0-x7:传递系统调用参数
  • 返回值存入x0

以write为例,macOS对应的系统调用编号为4(可通过macOS原生syscalls.master文件确认),直接替换动态库调用为系统调用即可彻底摆脱对_write符号的依赖:

修改后的汇编代码:

.global _main
.align 2

_main:
    stp x29, x30, [sp, #-16]!
    mov x29, sp

    ; 调用write系统调用:fd=1(标准输出),buf=hello,count=6
    mov x0, #1          ; 文件描述符
    adr x1, hello       ; 字符串地址
    mov x2, #6          ; 输出字节数
    mov x16, #4         ; macOS write系统调用号
    svc #0              ; 触发系统调用

    ; 调用exit系统调用:status=0
    mov x0, #0
    mov x16, #1         ; macOS exit系统调用号
    svc #0

hello:
    .ascii  "Hello\n"

这种方式完全不依赖动态库,可在Linux上用支持Mach-O输出的ARM64汇编器和链接器编译,示例命令:

aarch64-linux-gnu-as -o main.o main.s
aarch64-linux-gnu-ld -o main -arch arm64 -macosx_version_min 11.0 main.o

方案2:Linux上交叉编译Mach-O并正确处理动态链接

如果必须保留malloc/free等动态库函数调用,需在Linux上配置ARM64到macOS的交叉编译环境,让链接器自动生成符合Mach-O规范的动态链接信息,而非手动嵌入stub和GOT段:

  1. 安装交叉编译工具链
    使用osxcross工具链,它支持在Linux环境生成macOS兼容的Mach-O二进制。安装完成后,工具链前缀为aarch64-apple-darwin20-(对应macOS Big Sur及以上版本)。

  2. 修正汇编代码
    保留extern声明,但移除手动嵌入的stub/GOT段,让链接器自动处理动态链接逻辑:

.global _main
.align 2

_main:
    stp x29, x30, [sp, #-16]!
    mov x29, sp

    mov x0, #1
    adr x1, hello
    mov x2, #6
    bl _write           ; 由链接器自动生成动态链接相关的stub和GOT表

    mov x0, #0
    mov x16, #1
    svc #0

hello:
    .ascii  "Hello\n"

.extern _malloc
.extern _realloc
.extern _free
.extern _write
  1. 编译链接命令
    使用交叉编译工具链的汇编器和链接器,指定macOS系统库和SDK路径:
aarch64-apple-darwin20-as -o main.o main.s
aarch64-apple-darwin20-ld -o main -lSystem -syslibroot /path/to/osxcross/macosx.sdk main.o

其中-lSystem用于链接macOS系统库,-syslibroot指定macOS SDK的路径,链接器会自动生成正确的stub和GOT段,程序启动时macOS的dyld加载器会自动解析符号并更新GOT指针。


手动嵌入stub/GOT段无效的原因

Mach-O的动态链接依赖dyld加载器在程序启动时解析符号并更新GOT表,手动嵌入的GOT段没有被链接器标记为可重定位的动态符号表条目,dyld无法识别并更新这些地址。只有由链接器生成的GOT段才会包含正确的重定位信息,确保dyld在加载阶段完成符号解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:35:29