ARM64架构Mach-O文件修改.text段权限后崩溃及相关问题咨询
问题描述
我用MachOView这类可执行文件编辑器,把ARM64架构Mach-O文件的.text段权限从可读+可执行改成可读+可写+可执行后,程序一运行就崩溃。用lldb调试显示在main入口触发了EXC_BAD_ACCESS错误。
请问:
- 是否需要修改Mach-O文件的其他部分?如果需要,要改哪些?
- 如果没法用编辑器实现,手里有汇编源码的话,怎么在编译或链接阶段把
.text段设置成可写且可执行?
补充背景
我修改.text权限的原因是,下面这段汇编代码生成的可执行文件,系统加载时会调用fixupPage64()修正my_data的地址,但因为.text段不可写,程序触发总线错误终止。怎么解决ldr = Label_Address引发的运行崩溃问题?
汇编代码:
.text .globl _main .p2align 2 _main: func_constructor ldr x2,=my_data func_destructor ret .p2align 3 my_data: .quad 0x12345678aabbccdd
调试信息:
% lldb arm64 (lldb) target create "arm64" Current executable set to '/Users/hopy/src/asm/arm64' (arm64). (lldb) b main Breakpoint 1: where = arm64`main, address = 0x0000000100003f10 (lldb) r Process 2663 launched: '/Users/hopy/src/asm/arm64' (arm64) Process 2663 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x100003f10) frame #0: 0x0000000100003f10 arm64`main arm64`main: -> 0x100003f10 <+0>: sub sp, sp, #0x20 0x100003f14 <+4>: stp x29, x30, [sp, #0x10] 0x100003f18 <+8>: add x29, sp, #0x10 0x100003f1c <+12>: ldr x1, #0x8c ; my_data + 8 Target 0: (arm64) stopped.
解决方案
一、直接修改Mach-O文件的问题
直接用编辑器改.text段权限后崩溃,核心原因是Mach-O的段权限修改需要同步更新多个结构,不是只改段的flags就行:
- 必须同步修改
__TEXT段对应的vm_protection和max_vm_protection字段(在Mach-O的segment_command_64结构里),这两个分别控制运行时的实际权限和最大可调整权限。 - 另外,macOS/iOS的内核会强制校验可执行文件的W^X(写执行分离)安全规则,强行给
.text加写权限可能触发内核防护逻辑,直接导致加载崩溃。这种方式稳定性极差,不推荐。
二、汇编源码层面的正确解决方法
你的本质问题是:把my_data放在了.text段里,ldr x2,=my_data会生成需要重定位的地址,系统加载时要修改.text段内的重定位条目,但.text默认不可写,所以崩溃。根本不需要把整个.text改成可写,有两个更合理的方案:
方案1:把数据移到.data段
把my_data放到可写的.data段里,重定位时修改的是.data段内容,完全符合系统权限规则:
.text .globl _main .p2align 2 _main: func_constructor ldr x2,=my_data func_destructor ret .data .p2align 3 my_data: .quad 0x12345678aabbccdd
方案2:若必须把数据留在.text段,编译链接时设置权限
如果因为特殊需求必须让.text段可写可执行,可通过链接器参数实现:
- 编译汇编文件:
as -o main.o main.s - 链接时指定段权限:
ld -o arm64 main.o -segprot __TEXT rwx rwx-segprot参数格式为:-segprot 段名 运行时权限 最大权限,rwx代表可读可写可执行。
注意:这种方式会关闭系统的W^X防护,在现代macOS/iOS上可能被Gatekeeper等安全机制拦截,仅适合测试环境。
三、调试崩溃的额外说明
你调试时看到main入口触发EXC_BAD_ACCESS,是因为内核加载可执行文件时,发现.text段权限违反安全规则,直接拒绝执行,并非main函数指令本身有问题。解决权限或数据段的问题后,该崩溃会消失。
内容的提问来源于stack exchange,提问作者hopy
相关产品推荐
相关产品推荐

