MachO
MachO是Mach Object文件格式(Mach Object File Format)的缩写,是Mac/iOS上可执行文件的格式,类似于 Linux 和大部分 UNIX 的原生格式 ELF(Extensible Firmware Interface)以及 Windows 上的 PE。 包括如下格式
- 目标文件.o
- .a
- .dylib
- .framework
- 可执行文件 execute
- dyld
- .dsym
MachO 文件结构
MachO Header: Mach-O 的 CPU 类型、文件类型、加载命令的数量和大小等Load Commands
- 理解为书的目录,每个command对应后续代码和数据的具体组织结构,不同的数据类型使用不同的加载命令表示
- Segment Load Command 指向Data区域的Segment(段)
- PAGEZERO: 当设置一个指针变量的值为NULL时,其实就是将指针指向了__PAGEZERO段这块区域。
__TEXT: 代码段__DATA_CONST常量数据段__DATA其他数据段__LINKEDIT符号信息、代码签名等数据
- 每个Segment由多个Section(节)组成
- Data : 存放各类的代码和数据了
- Segments+Sections
MachOView
MachOView用于显示MachO文件的开源工具, 本文主要讲解MachOView的源码和MachO文件解析流程
读取Fat+Thin二进制信息
Mach-O 支持多架构在一个包中,如 armv7、arm64、x86-64等,俗称胖二进制/通用二进制(Fat)
- 针对Fat二进制文件, 会解析Fat + 每个子架构的信息, 如果是单架构,只会解析单个架构的信息
- 当读取结束后, MachOView中显示了Fat+Thin的二进制信息节点(FatLayout+MachOLayout)
- 这个可以理解为 RootNode, 每个架构一个 RootNode(Layout)
子Node创建总体流程
针对每个架构(Layout/Node)循环执行 MainTasks(同步) > BackgroundTasks(异步)
MainTask
创建每个架构的 MachO Header + Load Command + Sections + Relocations(.o,.a) Node
Load Command 有如下种类
createLoadCommandNode执行完成后,所有的load command节点就创建完成了
创建每个Section的二进制内容节点, 作为后续的Background Task的父Node
Backgroud Tasks
创建各个section的子Node, 来显示更多的代码/数据信息
// 后台异步任务
- (void)doBackgroundTasks
{
NSBlockOperation * linkEditOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@"LinkEdit Parsing ..."]; // 通知UI刷新任务状态
[self processLinkEdit64]; // 创建符号表 外部符号表 代码签名等节点
}];
NSBlockOperation * sectionRelocsOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@"Section relocations Parsing ..."];
[self processSectionRelocs64]; // 针对.o .a 文件, 生成重定位Relocation节点信息
}];
NSBlockOperation * dyldInfoOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@"Dyld info Parsing ..."];
[self processDyldInfo]; // 生成dynamic loader信息节点
}];
NSBlockOperation * sectionOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@"Section contents Parsing ..."];
// 解析Section64的二进制显示可读的信息节点
// C String Literals、Floating Point Literals、Module、Symbol Stubs....
[self processSections64];
}];
NSBlockOperation * EHFramesOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@" Exception Frames Parsing ..."];
[self processEHFrames64]; // Exception Frames
}];
NSBlockOperation * LSDAsOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@" Lang Spec Data Areas Parsing ..."];
[self processLSDA64]; // Lang Spec Data Areas
}];
NSBlockOperation * objcSectionOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@" ObjC Section contents Parsing ..."];
[self processObjcSections64]; // 解析Section64 中的OC信息
}];
NSBlockOperation * codeSectionsOperation = [NSBlockOperation blockOperationWithBlock:^
{
[dataController updateStatus:MVStatusTaskPendding :@" Code sections Parsing ..."];
[self processCodeSections64]; //解析Section Text端,反汇编
}];
// Block任务按顺序执行
[sectionOperation addDependency:linkEditOperation];
[sectionRelocsOperation addDependency:sectionOperation];
[dyldInfoOperation addDependency:sectionRelocsOperation];
[objcSectionOperation addDependency:dyldInfoOperation];
[codeSectionsOperation addDependency:objcSectionOperation];
[EHFramesOperation addDependency:dyldInfoOperation];
[LSDAsOperation addDependency:EHFramesOperation];
[dataController updateStatus:MVStatusTaskStarted];
[oq addOperations:[NSArray arrayWithObjects:linkEditOperation,
sectionOperation,
sectionRelocsOperation,
dyldInfoOperation,
EHFramesOperation,
LSDAsOperation,
objcSectionOperation,
codeSectionsOperation,nil]
waitUntilFinished:YES]; // 在后台线程执行
[dataController updateStatus:MVStatusTaskTerminated];//完成所有解析任务
- Dynamic Loader Info+LinkEdit后的Node信息
- processCodeSections : 解析__Text.__text Section, 显示汇编代码
- processSections64 : 解析Section的二进制显示C String Literals、Floating Point Literals、Module、Pointer、Symbol Stubs....
- processObjcSections64 : 解析Section的OC信息
CFString, Class, Category,protocol,Image....
更多信息
- MachOView
- 官网macho介绍
- API参考