Mach-O文件简介
Mach-O 是Mach Object文件格式的缩写,是运用于mac以及iOS上;它是一种用于可执行文件、目标代码、动态库的文件格式;
Mach-O文件类型
- Executable:应用可执行的二进制文件
- Dylib Library:动态链接库
- Static Library:静态链接库
- Bundle:不能被链接 Dylib,只能在运行使用dlopen()加载
- Relocatable Object File:可重定向文件
Mach-O文件结构
- Header:快速确认Mach-O文件的基本信息
- LoadCommand:加载指令,告诉加载器如何处理二进制数据,处理对方分别为内核,动态链接器等
-
Data:函数符号关联操作等
- Header
类型:区分32位、64位
结构:
// 32位
struct mach_header {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
};
// 64位
struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
};
注释:
magic
:确定Mach-O文件运行框架,如64位/32位
cpu
:CPU类型,如arm
cpusubtype
:对应CPU类型的具体型号
filetype
:文件类型
ncmds
:加载命令条数
sizeofcmds
:所有加载命令的大小
flags
:保留字段
reserved
:标志位
- LoadCommand
- cmd:指令类型
- cmdsize: 指令长度
结构
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
- command 指令类型说明
LC_SEGMENT/LC_SEGMENNT_64
- 作用:将对应段中的数据加载并映射到进程的内存空间
LC_SEGMENT_TEXT
- 作用:代码段,其中_stub_helper用于关联函数bind/rebind
LC_SEGMENT_DATA
- 作用:可读/可写的数据段,函数指针,其中_la_symbol_ptr动态函数个数,及相对动态符号表的偏移量
LC_SEGMENT_LINKEDIT
- 作用:动态链接加载指令,支持动态链接dyld,该段长度覆盖符号表等数据(计算链接时程序的基址),符号表,动态符号表,字符串表段中定义的offset偏移量都是基于_LINKEDIT的vm_add
LC_SYMTAB
- 作用:符号表信息,解析函数名
LC_DYSYMTAB
- 作用:动态符号表信息,地址值为动态函数相对符号表的索引,_la_symbol_ptr对应的cmd可以换算出第一个动态函数对应动态符号表的初始地址,其次存储是连续,结构长度固定的,可以通过遍历获取所有动态函数的对应的符号表索引
- Data
结构:
- Symbol Table: 符号表
- Dynamic Symbol Table: 动态符号表
- Section: 符号和函数相关联
// Section的数据结构
struct section { /* for 32-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint32_t addr; /* memory address of this section */
uint32_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
};
补充:
lipo命令
使用lifo -info 可以查看MachO文件包含的架构
$lipo -info MachO文件
使用lifo –thin 拆分某种架构
$lipo MachO文件 –thin 架构 –output 输出文件路径
使用lipo -create 合并多种架构
$lipo -create MachO1 MachO2 -output 输出文件路径