Mach-O其实是
Mach Object
文件格式的缩写,是Mac以及iOS上可执行文件的格式,类似于Win上的PE(Portable Executable)格式,Linux上的elf(Executable and Linking Format)格式。
Mach-O文件
Mach-O是一种用于可执行文件,目标代码,动态库,内核转储的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性,并提升了符号表中信息的访问速度。
Mach-O格式的常见文件
- 可执行文件
- 目标文件.o
- 库文件(.a、.dylib、Framework)
- dyld
- .dsym
File指令
通过file 文件路径
查看文件类型
Mach-O文件结构
通用二进制文件(Universal Binary)
- Apple公司提出了一种程序代码,能同时使用多种架构的二进制文件。
- 同一个程序包中同时为多种架构提供理想的性能。
- 因为需要存储多种代码,通用二进制应用程序通常币单一平台二进制的程序要大。
- 但是由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多。
- 而且由于执行中只调用一部分代码,运行并不会产生而外的内存消耗。
一个Mach-O中,通常存在这多种架构,为了便于分析,一般我们会拆分架构,去分析单一到架构,一来提升解析速度,二来方便分析。
- 使用
lipo -info Mach-O
查看Mach-O文件所包含到架构- 使用
lipo Mach-O -thin 架构(arm64) -output 输出的文件
拆分指定架构- 使用
lipo -create MachO1 MachO2 -output 输出文件
合并多种架构
文件结构
- Header包含该二进制文件的一般信息
struct mach_header_64 {
uint32_t magic; //包含一个值的整数,该值用于将Mach-O标识文件是32位还是64位
cpu_type_t cputype; //指示要在其上使用文件的体系结构的整数,x86/ARM等
cpu_subtype_t cpusubtype; //指定CPU的精确模型的整数,arm64/armv7等
uint32_t filetype; //文件类型,比如可执行文件
uint32_t ncmds; //loadCommands条数
uint32_t sizeofcmds; //loadCommands的大小
uint32_t flags; //标志位,标识二进制文件支持的功能,主要是和系统加载、链接相关
uint32_t reserved; //64位新增的保留位
}; //以64位体系结构为目标的目标文件的开头
-
Load commands 一张包含很多内容的表
内容包括区域的位置、符号表、动态符号表等。
- LC_SEGMENT_64:将文件中(32/64位)的段映射到进程地址空间中
- LC_DYLD_INFO_ONLY:动态链接相关信息
- LC_SYMTAB:符号地址
- LC_DYSYMTAB:动态符号表地址
- LC_LOAD_DYLINKER:使用的加载器,dyld加载器
- LC_UUID:文件的UUID
- LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS:支持的最低操作系统版本
- LC_SOURCE_VERSION:源代码版本
- LC_MAIN:设置程序主线程的入口地址和栈大小
- LC_ENCRYPTION_INFO_64:获取加密信息
- LC_LOAD_DYLIB:依赖库的路径,包含三方库
- LC_FUNCTION_STARTS:函数其实地址表
- LC_DATA_IN_CODE:定义在代码段内的非指令的表
- LC_CODE_SIFNATURE:代码签名
-
Data通常是对象文件中最大的部分
- 存放数据:代码、字符常量、类、方法等
- 一般拥有多个Segment,每个Segment拥有零到多个Section。每个段都有一段虚拟地址映射到进程到地址空间。
-
Loader Info动态到链接信息
- 一个完整的用户级Mach-O文件的末端是一系列链接信息。其中包含了动态加载器用来链接可执行文件或者依赖所需使用的符号表、字符串表等