dyld加载流程

dyld加载流程

配置环境变量依赖DYLD(dyld)
dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统的重要组成部分,在app被编译打包成可执行文件格式的Mach-O文件后,交由dyld负责连接,加载程序

image.jpeg


app启动的起始点

image.jpeg


【app启动起点】:通过程序运行发现,是从dyld中的_dyld_start开始的,

image.jpeg

源码中搜索dyldbootstrap找到命名作用空间,再在这个文件中查找start方法,其核心是返回值的调用了dyld的main函数

在_main函数中主要做了一下几件事情:
【第一步:环境变量配置】:根据环境变量设置相应的值以及获取当前运行架构
【第二步:共享缓存】:检查是否开启了共享缓存,以及共享缓存是否映射到共享区域,例如UIKit、CoreFoundation等
【第三步:主程序的初始化】:调用instantiateFromLoadedImage函数实例化了一个ImageLoader对象
【第四步:插入动态库】:遍历DYLD_INSERT_LIBRARIES环境变量,调用loadInsertedDylib加载
【第五步:link 主程序】
【第六步:link 动态库】
【第七步:弱符号绑定】
【第八步:执行初始化方法】
【第九步:寻找主程序入口即main函数】:从Load Command读取LC_MAIN入口,如果没有,就读取LC_UNIXTHREAD,这样就来到了日常开发中熟悉的main函数了
第三步:主程序初始化
sMainExecutable表示主程序变量,查看其赋值,是通过instantiateFromLoadedImage方法初始化

image.jpeg

进入instantiateFromLoadedImage源码,其中创建一个ImageLoader实例对象,通过instantiateMainExecutable方法创建


image.jpeg

进入instantiateMainExecutable源码,其作用是为主可执行文件创建映像,返回一个ImageLoader类型的image对象,即主程序。其中sniffLoadCommands函数时获取Mach-O类型文件的Load Command的相关信息,并对其进行各种校验


image.jpeg

上面的第八步:执行初始化方法
进入initializeMainExecutable源码,主要是循环遍历,都会执行runInitializers方法

image.jpeg

notifySingle 函数
发现在_dyld_objc_notify_register进行了调用
_dyld_objc_notify_register,发现在_objc_init源码中调用了该方法,并传入了参数,所以sNotifyObjCInit的赋值的就是objc中的load_images,而load_images会调用所有的+load方法。所以综上所述,notifySingle是一个回调函数

image.jpeg

load函数加载
下面我们进入load_images的源码看看其实现,以此来证明load_images中调用了所有的load函数

通过objc源码中_objc_init源码实现,进入load_images的源码实现


image.jpeg

进入call_load_methods源码实现,可以发现其核心是通过do-while循环调用+load方法


image.jpeg

【总结】load的源码链为:_dyld_start --> dyldbootstrap::start --> dyld::_main --> dyld::initializeMainExecutable --> ImageLoader::runInitializers --> ImageLoader::processInitializers --> ImageLoader::recursiveInitialization --> dyld::notifySingle(是一个回调处理) --> sNotifyObjCInit --> load_images(libobjc.A.dylib)

image.jpeg

你可能感兴趣的:(dyld加载流程)