Mach-O文件结构
status
category
date
summary
slug
icon
tags
password
本文源码从苹果开源官网获得
什么是Mach-O
Mach-O
为 Mach Object
文件格式的缩写,是用于 iOS 和 macOS 的可执行文件,目标代码,动态库,内核转储的文件格式。Mach-O 文件格式
苹果官方给的一张文件结构图:

我们编写一个HelloWorld程序,将其编译,然后通过MachOView来打开.out文件:

可以知道Mach-O由三部分组成: *
Header
:指明了CPU架构、文件类型、Load Commands 个数等一些基本信息。 * Load Commands
:描述了怎样加载每个 Segment 的信息。在 Mach-O 文件中可以有多个 Segment,每个 Segment 可能包含零个、一个或多个 Section。 * Data
:Segment 的具体数据,包含了代码和数据等。Header
magic
:魔数,0xfeedface是32位,0xcefaedfe是64位
cputype
:CPU类型
cpusubtype
:CPU具体类型
filetype
:文件类型,例如可执行文件、库文件等 文件类型filetype的宏定义有:
ncmds
:Load Commands的数量
sizeofcmds
:Load Commands的总大小
flags
:标志位,用于描述该文件的详细信息。
reserved
:64位才有的保留字段,暂时没用
标志位flags的宏定义有:
对于上面的HelloWorld程序来说,它的Header信息如下:

Load Commands
cmd
类型:指定command类型
cmdsize
:表示command大小,用于计算到下一个command的偏移量
cmd类型:
cmd | 作用 |
LC_SEGMENT/LC_SEGMENT_64 | 将段内数据加载映射到内存中去 |
LC_SYMTAB | 符号表信息 |
LC_DYSYMTAB | 动态符号表信息 |
LC_DYLD_INFO_ONLY | 动态库信息 |
LC_LOAD_DYLINKER | 启动dyld |
LC_UUID | 唯一标识符 |
LC_SOURCE_VERSION | 源代码版本 |
LC_MAIN | 程序入口 |
LC_LOAD_DYLIB | 加载动态库 |
LC_FUNCTION_STARTS | 函数符号表 |
LC_DATA_IN_CODE | Data注入代码地址 |
| LC_CODE_SIGNATURE|代码签名信息| | ㅤ |
segment

首先看看segment的定义:
cmd
:上面提到的Load Command类型
cmdsize
:Load Command大小
segname[16]
:段名称

segname | 含义 |
__PAGEZERO | 可执行文件捕获空指针的段 |
__TEXT | 代码段和只读数据 |
__DATA | 全局变量和静态变量 |
| __LINKEDIT | 包含动态链接器所需的符号、字符串表等数据 | ㅤ |
vmaddr
:段虚拟地址(未偏移),真实虚拟地址要加上ASLR的偏移量
vmsize
:段的虚拟地址大小
fileoff
:段在文件内的地址偏移
filesize
:段在文件内的大小 加载segment的过程,就是从文件偏移fileoff
处,将大小为filesize
的段,加载到虚拟机vmaddr
处。
nsects
:段内section数量
flags
:标志位,用于描述详细信息 标志位宏定义:
section
section的定义:
sectname
:section名称
segname
:所属的segment名称 (大写的__TEXT
代表segment
,小写的__text
代表section
)

sectname | 含义 |
__text | 主程序代码 |
__subs | 桩代码 |
__stub_helper | 用于动态链接,启动dyld |
__cstring | 硬编码的C字符串 |
__la_symbol_ptr | 延迟加载 |
| __data | 初始化的可变的变量 | ㅤ |
addr
:section在内存中的地址
size
:section大小
offset
:section在文件中的偏移
align
:内存对齐边界
reloff
:重定位入口在文件中的偏移
nreloc
:重定位入口数量
Loading...