iOS程序启动之dyld

一、dyld简介:

dyld全名为dynamic loader(动态链接器)(默认路径是/usr/lib/dyld)。
当一个iOS应用程序启动时,系统会先读取App的可执行文件(Mach-O文件),从里面获得dyld的路径,然后加载dyld,dyld去初始化运行环境,开启缓存策略,加载程序相关依赖库(其中也包含我们的可执行文件),并对这些库进行链接,最后调用每个依赖库的初始化方法,在这一步,runtime被初始化。当所有依赖库的初始化后,轮到最后一位(程序可执行文件)进行初始化,在这时runtime会对项目中所有类进行类结构初始化,然后调用所有的load方法。最后dyld返回main函数地址,main函数被调用,我们便来到了熟悉的程序入口。

查看dyld源码

从上述程序加载流程可大概得知,dyld就是负责将我们程序的可执行文件和系统提供的动态库进行链接,并执行一系列的程序初始化操作:

二、dyld执行过程:

  1. 通过配置上下文信息,设置运行环境,处理环境变量,获取主机信息等。

2.检查共享缓存是否已经映射到共享区域

3.加载system frameWork

调用 instantiateFromLoadedImage 函数实例化一个 ImageLoader 对象。该函数先调用 isCompatibleMachO 来判断文件的架构是否和当前的架构兼容,然后调用 ImageLoderMachO::instantiateMainExecutable 来加载文件生成实例,并将 image 添加到全局 sAllImages 中。

4.加载所有插入的dylib

通过遍历 DYLD_INSERT_LIBRARIES 环境变量,调用 loadInsertedDylib 加载。

在三方App的Mach-O文件中通过修改DYLD_INSERT_LIBRARIES的值来加入我们自己的动态库,从而注入代码,hook别人的App。

5.链接主程序

调用 link 链接主程序。内核调用的是ImageLoader::link 函数。

6.通过link函数链接所有插入的库,执行符号替换

对 sAllimages (除了主程序的Image外)中的库调用link进行链接,然后调用 registerInterposing 注册符号插入。

对插入的库进行链接。其主要做的事有对image进行load(加载), rebase(基地址复位),bind(外部符号绑定)

我们可以在程序中设置环境变量DYLD_PRINT_INITIALIZERS为1来打印出程序链接的各种依赖库:

7.进行初始化操作

initializeMainExecutable 执行初始化方法,其中 +load 和 constructor 方法就是在这里执行。 initializeMainExecutable 内部先调用了动态库的初始化方法,后调用主程序的初始化方法。
initializeMainExecutable依次调用了 runInitializers、processInitializers、recursiveInitialization、notifySingle。

8.寻找主程序入口并执行

调用 getEntryFromLC_MAIN,从 Load Command 读取LC_MAIN入口,如果没有LC_MAIN入口,就读取LC_UNIXTHREAD,然后跳到入口处执行,这样就来到了我们熟悉的main函数处

链接:https://www.jianshu.com/p/73a99303cd91
链接:https://www.jianshu.com/p/43db6b0aab8e

你可能感兴趣的:(iOS程序启动之dyld)