前言
代码如何加载到内存的 我们探究一下
代码准备
1.应用程序的加载原理
库:可执行的二进制文件-> 能够被操作系统加载到内存->静态库 和 动态库
编译过程

可执行文件是什么呢
打开工程 command+b 入下图操作 最后得到的就是可执行文件



验证一下 可执行文件 执行了main函数里面的代码

可执行文件通过动态链接器dyld加载到内存的加载过程入下图

Runtime向注册回调函数是

加载新的image是指把库映射了一份到内存 通过代码 我们打印一下 image list 看加载了哪些dyld 通过地址找到CoreFoundation这个库 库的路径:对应dyld源码DYLD_ROOT_PATH

通过执行map_images 和 Load_images(这两个函数下篇在分析)之后 调用main函数
2.dyld引出
我们怎么找到dyld 首先打开工程 断点main函数

我们发现左边是0 main 1 start 在main之前走了这个1 start 1 start做了什么呢

欢迎来到 libdyld.dylib 的世界 添加系统断点start 走一波 发现没断点住 但是[ViewController load] 在main函数之前打印的 如果我们在这打印断点 看是否有发现呢 如下图

通过bt打印栈的信息 先进后出 所以最开始的是 dyld``_dyld_start 我们打开dyld源码(最新版本 dyld-852 下载链接在最上面)
应用加载流程如下
- dyld`_dyld_start ->
- dyld`dyldbootstrap::start ->
- dyld`dyld::_main ->
- dyld`dyld::useSimulatorDyld ->
- dyld_sim`dyld::_main ->
- dyld_sim`dyld::initializeMainExecutable() ->
- dyld_sim`ImageLoader::runInitializers ->
- dyld_sim`ImageLoader::processInitializers ->
- dyld_sim`ImageLoader::recursiveInitialization ->
- dyld_sim`dyld::notifySingle ->
- libobjc.A.dylib`load_images
3.dyld流程上
通过dyld源码搜索_dyld_start 我们进入汇编

发现会进入这个函数 call dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue) 我们全局搜索一下

该函数返回一个 dyld::_main((macho_header*)appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue); 我们进入看一下
4.dyld流程中的main函数主流程

因为main函数的代码比较长main函数最后返回result 通过反推 发现会执行 sMainExecutable这个函数

发现sMainExecutable = instantiateFromLoadedImage 这个函数实例化主程序

通过这个函数添加镜像文件

通过这个函数添加machO一些格式 machO的格式如下图:

通过sniffLoadCommands这个函数添加具体格式例如load_command

下一步加载插入的动态库


下一步 link主程序

下一步 link 插入动态库

下一步 weakBind弱引用绑定

下一步 初始化initializeMainExecutable 跑起来

下一步通知dyld可以进入main()函数了

5.dyld流程-主程序运行
我们主要分析initializeMainExecutable images开始初始化

进入 runInitializers -> processInitializers初始化准备

进入processInitializers->recursiveInitialization递归初始化

进入recursiveInitialization->context.notifySingle单个通知注入

-> doInitialization 调用init方法 -> context.notifySingle通知初始化完成

进入notifySingle->找到sNotifyObjCInit

通过sNotifyObjCInit->registerObjCNotifiers

通过registerObjCNotifiers->_dyld_objc_notify_register

而 _dyld_objc_notify_register 就是runtime注册回调函数
6.dyld流程-images初始化流程
我们通过objc4-818.2源码 断点_objc_init

libdispatch.dylib``_os_object_init

_os_object_init->调用了_objc_init

libdispatch.dylib``libdispatch_init->_os_object_init

libSystem.B.dylib``libSystem_initializer->libdispatch_init


dyld``ImageLoaderMachO::doModInitFunctions:->初始化libSystem_initializer(通过 strcmp(installPath, libSystemPath(context))


ImageLoaderMachO::doInitialization->doModInitFunctions

回到递归recursiveInitialization-> doInitialization

总结app启动流程图
























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)