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可以換算出第一個動態函數對應動態符號表的初始地址,其次存儲是連續,結構長度固定的,可以通過遍歷獲取所有動態函數的對應的符號表索引
LoadCommand
- 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 輸出文件路徑