Mach-O文件结构是什么?

摘要:Mach-O文件是Apple各种编译中间产物(比如.o)和最终编译产物(比如可执行二进制)使用的文件格式。 熟悉Mach-O格式,对于我们进行一些底层调试有帮助。 1 整体结构 Mach-O的整体结构如下: 2 Header Mach-O最
Mach-O文件是Apple各种编译中间产物(比如.o)和最终编译产物(比如可执行二进制)使用的文件格式。 熟悉Mach-O格式,对于我们进行一些底层调试有帮助。 1 整体结构 Mach-O的整体结构如下: 2 Header Mach-O最顶部是头信息。 头信息定义了这个Mach-O的基本信息,比如这个Mach-O使用的CPU架构、文件类型等。 头信息定义在XNU源码macho/loader.h中: 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 magic使用的常量为MH_MAGIC_64和MH_CIGAM_64。 对这两个值常见的一个误解是,以为MH_MAGIC_64代表Mach-O使用大端字节序,MH_CIGAM_64使用小端字节序。 而实际上是,如果Mach-O使用的字节序和后面cputype指定的CPU使用的字节序一样,那么就是MH_MAGIC_64。 反之,如果Mach-O使用的字节序和后面cputype指定的CPU使用的字节序相反,那么就是MH_CIGAM_64。 cputype cputype表示这个Mach-O文件要运行的CPU类型,比如是ARM64还是X86_64。 注意到这个字段的类型是cpu_type_t,它的定义如下: // mach/machine.h typedef integer_t cpu_type_t; typedef integer_t cpu_subtype_t; typedef integer_t cpu_threadtype_t; // mach/arm/vm_types.h typedef int integer_t; 从上面代码可以看到,cpu_type_t实际就是一个int类型。 cpusubtype 定义了CPU的子类型,比如CPU_SUBTYPE_ARM64_ALL。 filetype 常见的值如下: MH_OBJECT表明当前是一个.o文件。 MH_EXECUTE表明当前是一个可执行文件。 MH_DYLIB表明当前是一个动态链接库。 MH_PRELOAD这个类型已经废弃了。 MH_CORE表明当前是一个core文件。 程序崩溃后产生core文件,后续可以直接调试core文件定位问题,但是iOS应用不会产生这个文件类型。 MH_DYLINKER表明当前是一个动态链接器,dyld就是这个类型。 MH_DSYM表明当前是一个.dsym符号文件。 ncmds 文件后后面LC_Command的个数 sizeofcmds 所有LC_Command占用的字节数大小。 flags 常见的flags值如下: MH_NOUNDEFS表明当前Mach-O内没有未定义的引用。 MH_DYLDLINK表明当前Mach-O只能作为动态连接器的输入,不能再进行静态链接,可执行文件有这个标志。 MH_TOWLEVEL表明当前Mach-O使用二级命名空间,也就是说每一个外部符号都会记录它来自哪个库,避免名称冲突。 MH_PIE表明当前Mach-O会使用ASLR。 3 Load Command 紧接着Mach-O头信息的是一系列Load Command。 Load Command的种类很多,所有的Load Command开头的结构都是一样的: // mach-o/loader.h struct load_command { uint32_t cmd; /* type of load command */ uint32_t cmdsize; /* total size of command in bytes */ }; cmd 表明当前Load Command的类型。
阅读全文