苹果开发者对它必定不陌生,特别是喜欢逆向的同窗,对它的研究更是必不可少。在可安装的每个.app包中,都有一个与app同名的可执行文件,它可能长这样:(若是你碰到显示为白色的MachO文件,说明当前用户对其没有可执行权限) bash
lipo AlipayWallet -thin armv7 -output alipayArmv7
,一样也能用lipo create进行合并:
lipo alipayArm64 alipayArmv7 -create -output AlipayWalletNew
,你们能够本身实践一下。
来用MachOView验证一下该示例的MachO文件结构: markdown
除了用MachOView能查看MachO文件信息,还能够经过otool命令查看,咱们先来分析Header中的内容:otool -h AlipayWallet
: 数据结构
#define CPU_TYPE_ARM((cpu_type_t) 12) #define CPU_SUBTYPE_ARM_V7((cpu_subtype_t) 9) #define CPU_TYPE_ARM64((cpu_type_t) 16777228) #define CPU_SUBTYPE_AR64M_ALL((cpu_subtype_t) 0) 复制代码
#define MH_EXECUTE 0x2 /* demand paged executable file */ 复制代码
这里为你准备了 mach_header 的苹果官方文档说明:(更多详细定义请参考loader.h) 架构
咱们继续用命令查看:otool -l alipayArm64
,该示例共有75个加载指令,咱们只截取一个做为表明,分别为出如今segment和section中的每个参数进行注释:app
Load command 1 cmd LC_SEGMENT_64 // cmd 是load command的类型,LC_SEGMENT_64的含义是将这个64位的段映射到进程地址空间,即加载命令 cmdsize 712 // 表明load command的大小 segname __TEXT // 16字节的段名字 __TEXT vmaddr 0x0000000100000000 // 段的虚拟内存起始地址 vmsize 0x00000000036a4000 // 段的虚拟内存大小 fileoff 0 // 段在文件中的偏移量 filesize 57294848 // 段在文件中的大小 maxprot 0x00000005 // 段页面所须要的最高内存保护(4=r,2=w,1=x) initprot 0x00000005 // 段页面初始的内存保护 nsects 8 // 段中包含section的数量 flags 0x0 // 其余杂项标志位 Section sectname __text // 第一个是__text ,就是主程序代码 segname __TEXT // 该section所属的 segment名,第一个是__TEXT addr 0x0000000100006110 // 该section在内存的启始位置,0x100006110 size 0x000000000358a268 // size 该section的大小,0x358a268 offset 24848 // 24848 0x6110 align 2^4 (16) // 字节大小对齐,16 reloff 0 // 重定位入口的文件偏移 0 nreloc 0 // 须要重定位的入口数量 0 flags 0x80000400 // 包含section的type和attributes reserved1 0 // ...保留用 reserved2 0 // ...保留用 复制代码
注释完毕,我又为你准备了 segment和section 的苹果官方文档说明:(更多详细定义请参考loader.h) 函数
若是说前面两部分的主要做用,是让kern内核知道如何读取MachO文件,并指定MachO文件的动态连接器(dyly)用来完成后续的动态库加载,而后设置好程序入口等一些列程序启动前的信息,那么Data和连接信息部分,就至关于当程序运行起来后,为每个映射到虚拟内存中的指令操做提供真实的物理地址支持。详细的过程后面会单独写一篇文章展开来说。oop
理解原理很重要,了解MachO格式的结构和加载运行,不只能够帮助咱们理解MacOS和iOS的app可执行文件启动过程,还能作且不限于:post
但愿你有所收获!下篇咱们主要围绕dyld讲动态加载过程,see you~学习
参考文章:优化