iOS-二进制重排

194 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

通过问题看本质!!!

APP启动分为两种

冷启动

APP启动前,APP的进程不在系统里,需要系统创建进程分配给APP。 APP进程不在系统里,需要开启新进程。

热启动

APP在冷启动后,用户将APP退到后台,用户重新回到APP。

或者立刻重启,因为进程缓存还存在。

APP进程在系统里,不需要开启新进程。

启动流程三阶段

1、main函数执行之前;

2、main函数执行之后;

3、首屏幕渲染完成后。

二进制重排

二进制重排是main函数执行之前的优化。

APP启动的时候,启动加载的符号是按照Xcode->Targets->Build Phases->Compile Sources的顺序,而不是按照方法调用的顺序。所以我们需要把启动时调用方法的符号获取到,但是要如何获取呢?

  1. Fishhook无法hook所有的方法,而且需要修改汇编代码,因为参数不确定。
  2. 静态扫码 :扫描特定段和字节的符号和函数数据。
  3. 通过clang静态插桩的方式,在编译阶段就在每一个函数的内部二进制数据添加hook代码。

毫无疑问我们用的是clang静态插桩的方式

二进制重排是利用符号的顺序,重新排列代码在文件中的偏移地址,将启动需要加载的方法地址放在前面的页内存中,减少页中断的次数,从而达到优化效果。

APP启动时候使用到的符号,是通过clang静态插桩的方式获取的。在编译阶段就在每一个函数的内部二进制数据添加hook代码,把启动加载用到的符号按顺序写入order文件中,再把路径配置到ld链接器中。这样编译链接的时候就可以按照文件中符号的顺序进行生成对象的mach-o文件。