MacOS ARM64架构下mmap创建RWX页面失败求助
解决ARM64 macOS下mmap映射RWX内存失败的问题
在ARM64架构的macOS上,苹果强制启用W^X(写或执行二选一)的内存安全机制,即使禁用SIP也无法直接映射同时可写可执行的内存页,这就是你收到EACCES错误的核心原因。x64 Catalina允许直接映射RWX是因为旧架构的安全规则相对宽松,但ARM64从设计上就严格执行W^X机制。
针对你的FORTH自修改代码需求,正确的操作流程是分两步完成:
1. 先映射可读写(RW)内存页
先申请一块仅可读写的内存区域,用于生成或修改代码:
mov x0, 0 // 让内核自动分配起始地址 mov x1, 4096 // 内存页长度(4KB) mov x2, 0x3 // 权限:PROT_READ | PROT_WRITE (0x1 | 0x2) mov x3, 0x1001 // flags:MAP_PRIVATE | MAP_ANON (0x1000 | 0x1) mov x4, -1 // 文件描述符:-1对应匿名映射 mov x5, 0 // 文件偏移:0(匿名映射无需关心) mov x16, 0x200005c // mmap系统调用号 svc 0 // 检查返回值:若x0为-1(即0xFFFFFFFFFFFFFFF),说明映射失败 cmp x0, #-1 b.eq mmap_fail
2. 将内存权限修改为可读可执行(RX)
当代码生成完成后,调用mprotect将内存权限切换为可执行:
// x0保留第一步mmap返回的内存起始地址 mov x1, 4096 // 要修改权限的内存长度 mov x2, 0x5 // 权限:PROT_READ | PROT_EXEC (0x1 | 0x4) mov x16, 0x200005d // mprotect系统调用号 svc 0 // 检查返回值:0表示成功,-1表示失败 cmp x0, #-1 b.eq mprotect_fail
如果后续需要再次修改这段代码,只需重复反向操作:
- 调用
mprotect将权限改回RW(0x3) - 修改代码内容
- 再次调用
mprotect改回RX(0x5)
这种方式完全适配FORTH运行时自修改代码的需求,同时符合ARM64 macOS的内存安全规则。
内容的提问来源于stack exchange,提问作者Klapaucius Klapaucius
相关产品推荐
相关产品推荐

