Apple Silicon ARM64环境下jmp_buf存储寄存器及SDK注释疑问
Apple Silicon Mac 中 jmp_buf 寄存器存储的疑问与验证方法
在Apple Silicon Macbook上编写原生协程时,需要用到setjmp.h中的jmp_buf保存上下文,因此需要明确jmp_buf中具体存储哪些寄存器。查看MacOSX 13.3 SDK中的setjmp.h文件时,发现代码注释与宏定义存在矛盾。
存在矛盾的SDK代码
/* * _JBLEN is the number of ints required to save the following: * r21-r29, sp, fp, lr == 12 registers, 8 bytes each. d8-d15 * are another 8 registers, each 8 bytes long. (aapcs64 specifies * that only 64-bit versions of FP registers need to be saved). * Finally, two 8-byte fields for signal handling purposes. */ #define _JBLEN ((14 + 8 + 2) * 2) typedef int jmp_buf[_JBLEN]; typedef int sigjmp_buf[_JBLEN + 1]; #else # error Undefined platform for setjmp #endif
宏_JBLEN定义为((14 + 8 + 2) * 2),但注释中称是12个通用寄存器加8个浮点寄存器。根据ARM64架构资料,x19-x28是被调用者保存寄存器(共10个),加上x29(fp)、x30(lr)、x31(sp)、pc,总共14个通用寄存器,这与宏中的14对应。疑惑是注释错误还是自身计算有误?另外,如何准确确定jmp_buf中存储的寄存器?若MacOSX SDK的注释确实错误,该如何修正?
一、注释错误的确认
注释确实存在错误:
- 注释里的
r21-r29, sp, fp, lr == 12 registers描述有误:- ARM64架构下,被调用者保存的通用寄存器是x19-x28(共10个),而非r21-r29(这是ARM32的寄存器命名规则);
- 加上x29(fp)、x30(lr)、x31(sp)、pc(程序计数器),总共14个通用寄存器,这与宏定义中的
14完全对应; - 注释中“12个寄存器”的说法错误,实际应为14个通用寄存器。
二、准确确定jmp_buf存储寄存器的方法
- 查看苹果开源libc代码:苹果会开源系统级组件代码,ARM64架构下的
setjmp实现(通常在libc/arm64目录下的setjmp.s等汇编文件)会明确写出哪些寄存器被写入jmp_buf,是最权威的参考。 - 调试对比验证:编写简单测试程序,先读取被调用者保存寄存器(如x19-x28、fp、lr)的值,调用
setjmp保存上下文后,打印jmp_buf的内容,对比寄存器值与jmp_buf中对应位置的数据,即可确定每个位置对应的寄存器。 - 参考AAPCS64规范:Apple Silicon遵循ARM的AAPCS64规范,其中明确要求
setjmp需要保存被调用者保存的通用寄存器、d8-d15浮点寄存器(被调用者保存的浮点寄存器),以及信号处理相关字段,这与代码中注释提到的d8-d15和信号字段的描述一致。
三、SDK注释的修正方式
- 本地修改(仅供个人参考):直接修改本地SDK中的
setjmp.h文件,将注释中的错误内容替换为正确描述:* x19-x28, sp, fp, lr, pc == 14 registers, 8 bytes each. d8-d15 - 避免影响系统编译:更稳妥的方式是不修改系统SDK文件,而是在自己的项目中添加备注说明该注释错误,或者复制一份修正后的头文件到项目本地,仅在自己的代码中引用。
内容的提问来源于stack exchange,提问作者Edenlia
相关产品推荐
相关产品推荐

