Mach-O是一种文件的格式; 是iOS/Mac OS上存储程序以及库的标准格式
类型
1 | #define MH_OBJECT 0x1 /* 目标文件 例如:.o 、.a 、.framework(静态库) */ |
基本结构
Mach-O 包含三个主要区域
Header: 文件类型, 目标架构
Load command: 描述文件在虚拟内存中的逻辑与布局
Raw segment date : Load command中定义的原始数据
可以从我的仓库下载 Mach-O View 来查看文件的结构
使用 Mach-O View 来打开可执行文件
由于上图的可执行文件只适配了ARM64,一般通用可以执行文件如图下
含有多个不同架构的独立二进制文件; 故体积较大
执行时, 只会选择一种架构的二进制文件
Mach Header
Magic Number 表示支持设备的CPU位数
- oxFEEDFACE : 表示32位二进制
- oxFEEDFACF : 表示64位二进制
cputype和 cpusubtype: CPU类型和子类型
- filetype : Mach-O文件类型
- ncmds 和 sizeofcmds: 用于加载器的 加载命令的条数和大小
- flags : 动态链接器dyld的标志
SEGMENT(LC_SEGMENT / LC_SEGMENT_64)
- __PAGEZERO: 空指针陷阱段
- _TEXT: 程序代码段
- __DATA: 程序数据段
- __RODATA: read only程序只读数据段
__LINKEDIT: 链接器使用段
Section
- Segment Name: 该Segment的名称, 用于load_segment
- VM Address: 该段的虚拟物理地址
- VM Size: 该段所需要分配的虚拟内存大小(字节)
- File Offset: 该段在文件中的偏移量
- File Size: 该段在文件中占据的字节数
- Maximum VM Protection: 段的页面所需要的最高内存保护
- ox1: x 执行
- ox2: w 写
- 0x4: r 读
- Initial VM Protection: 段页面初始化的内存保护
- Number of Sections: 段中section区的数量
- Flags: 其他标志位
1 | 根据LC_SEGMENT命令 设置进程虚拟内存 |
常见区section
- __text: 主程序代码
- __stubs, __stub_helper: 用于动态链接的桩
- __cstring: 程序中c语言字符串
- __const: 常量
- __RODATA, __objc_methname: OC方法名称
- __RODATA, __objc_methntype: OC方法类型
- __RODATA, __objc_classname: OC类名
- __DATA, __objc_classlist: OC类列表
- __DATA, __objc_protollist: OC原型列表
- __DATA, __objc_imageinfo: OC镜像信息
- __DATA, __objc_const: OC常量
- __DATA, __objc_selfrefs: OC类自引用(self)
- __DATA, __objc_superrefs: OC类超类引用(super)
- __DATA, __objc_protolrefs: OC原型引用
- __DATA, __bss: 没有初始化和初始化为0 的全局变量
关于 LoadCommand
LC_MAIN
设置程序主线程入口地址 和 栈大小
LC_CODE_SIGNATURE
- 包含Mach-O文件的代码签名
- 没有签名 或 签名不正确, 该进程会被kill, 程序崩溃
关于动态库
即Mach-O镜像中有很多对外部库以及符号的引用
这些引用将在程序启动时, 由动态链接器 /usr/lib/dyld来执行符号绑定
加载动态链接器
LC_LOAD_DYLINKER: 内核执行该命令时, 启动dyld
符号表
LC_SYMTAB: 符号地址表
LC_DYSYMTAB: 动态符号地址表
加载动态库
LC_LOAD_WEAK_DYLIB
LC_LOAD_DYLIB
1 | 动态库加载流程小结: |
关于 符号表 、动态符号表 和 字符串表
- Symbol Table: 符号表
- Dynamic Symbol Table: 动态符号表
- String Table: 字符串表