拜伦的博客

Coder Byron

这里有关于iOS,机器学习的笔记心得,欢迎交流


Mach-O文件初识

目录

Mach-o 文件

Mach-O格式全称为Mach Object文件格式的缩写,是mac上可执行文件的格式

Mach-O 文件构成如下

Headers

保存了一些基本信息,包括了该文件运行的平台、文件类型、LoadCommands的个数等等。Headers的主要作用就是帮助系统迅速的定位Mach-O文件的运行环境,文件类型,保存了一些dyld重要的加载参数。 Mach-O 文件的头部定义如下:

  • magic 标志符 0xfeedface 是 32 位, 0xfeedfacf 是 64 位。
  • cputype 和 cpusubtype 确定 cpu 类型、平台
  • filetype 文件类型,可执行文件、符号文件(DSYM)、内核扩展等
  • ncmds 加载 Load Commands 的数量
  • flags dyld 加载的标志
    • MH_NOUNDEFS 目标文件没有未定义的符号,
    • MH_DYLDLINK 目标文件是动态链接输入文件,不能被再次静态链接

    • MH_SPLIT_SEGS 只读 segments 和 可读写 segments 分离
    • MH_NO_HEAP_EXECUTION 堆内存不可执行

header的作用是保存Mach-O可执行文件需要的环境和合法性。

Load Commands

可以理解为加载命令,在加载Mach-O文件时会使用这里的数据来确定内存的分布以及相关的加载命令。比如我们的main函数的加载地址,程序所需的dyld的文件路径,以及相关依赖库的文件路径。

  • cmd 字段表示command 类型
  • cmdsize 字段标识command占用地址长度,即到下一个command的偏移量

Data & Segment

每一个segment的具体数据都保存在这里,这里包含了具体的代码、数据等

截屏2020-09-23 上午10.10.27 数据页的概念,segname 是数据页类型

  • #define SEG_PAGEZERO “__PAGEZERO” // 可执行文件捕获空指针的段
  • #define SEG_TEXT “__TEXT” // 代码段,只读数据段
  • #define SEG_DATA “__DATA” // 数据段
  • #define SEG_LINKEDIT “__LINKEDIT” // 包含动态链接器所需的符号、字符串表等数据

Section

截屏2020-09-23 上午10.11.03 数据页中的子分区。sectname表示自己所在分区名称

  • Text.__text 主程序代码
  • Text.__cstring c 字符串
  • Text.__stubs 桩代码
  • Text.__stub_helper
  • Data.__data 初始化可变的数据
  • Data.__objc_imageinfo 镜像信息 ,在运行时初始化时 objc_init,调用 load_images 加载新的镜像到 infolist 中
  • Data.__la_symbol_ptr
  • Data.__nl_symbol_ptr
  • Data.__objc_classlist 类列表
  • Data.__objc_classrefs 引用的类

了解Mach-O的作用

分析可执行文件结构,对于逆向砸壳、调取堆栈信息、分析代码组成等有重要帮助。这里介绍分析代码组成减少安装包大小。

由于 OC 的动态特性,编译器会对所有的源文件进行编译,并连接进可执行文件中,增大了安装包的大小。 上文中提到了 __objc_classlist 和 __objc_classrefs,它们分别表示项目中全部类列表和项目中被引用的类列表,那么取两者之差,就能删除一些项目中没使用的类文件。但是在删除过程中记住要在项目中全局搜索确认下,看看有没有通过字符串调用无引用的类的方法,原因还是 OC 是动态语言。

详细过程见iOS删除无用的类iOS项目优化iOS删除无用的方法

查看工程中代码量大的库或类

通过linkMap文件,可分析出各个类和库占用的大小,用来优化库或代码的数量。 在build setting中打开 link map的开关,在drivedata中找到编译产生的link map文件。

更多详情见对Mach-O文件的初步探索

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦