12.应用程序加载

222 阅读2分钟

一、dyld的引出

1.首先在main函数打断点,可以看到在main之前libdyld.dylib`start

image.png

2.在load函数打断点,通过堆栈信息可以看到dyld做了大量的工作

image.png

3.dyld可以从苹果官网下载

地址: opensource.apple.com/release/mac…

二、dyld中main函数流程

1.全局搜索_dyld_start,根据注释可以知道最终是调用了dyldbootstrap::start

image.png

2.全局搜索dyldbootstrap,可以看到start函数

image.png

3.在start函数中,返回了_main

image.png

4.简单来看_main函数,直接看最后一行,返回result,在寻找result赋值的地方,发现和sMainExecutable有关,再找和sMainExecutable赋值相关的代码,在7009行可以看到

	sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);

5.instantiateFromLoadedImage初始化主程序

image.png

6.7241行initializeMainExecutable

image.png

7.runInitializers函数

image.png

8.processInitializers函数

image.png

9.recursiveInitialization函数(1654行依赖文件的加载完成通知,1662行本身加载完成通知)

image.png

10.notifySingle函数(1112行sNotifyObjCInit)

image.png

11.registerObjCNotifiers函数给sNotifyObjCInit赋值了

image.png

12._dyld_objc_notify_register函数调用了registerObjCNotifiers

image.png

13.在runtime源码中调用了dyld中的_dyld_objc_notify_register函数

image.png

14.在runtime源码_objc_init打断点,查看堆栈

image.png

15.下载libdispatch库,搜索_os_object_init函数

image.png

16.在libdispatch_init函数7923行中

image.png

17.下载libSystem库,搜索libSystem_initializer函数239行

image.png

18.回到dyld,搜索doModInitFunctions函数

2318行判断如果libSystemPath库没初始化完成,就会抛出异常

2326行func执行调用,2310行func = inits[j],即会调用libSystem_initializer image.png

19.doInitialization函数

image.png

20.而调用doInitialization函数是在recursiveInitialization函数中

image.png

21.回到runtime _objc_init函数中

image.png

22.在dyld中 registerObjCNotifiers赋值了参数

image.png

23.搜索sNotifyObjCMapped,在notifyBatchPartial函数中调用

image.png

24.搜索sNotifyObjCInit,在notifySingle函数中

image.png

25.notifySingle函数调用是在recursiveInitialization函数中

26.工程中的加载顺序 load函数->C++函数->main函数

27.runtime中的load_images函数

image.png

28.prepare_load_methods函数

image.png

29.schedule_class_load函数

image.png

30.add_class_to_loadable_list函数收集load放在到loadable_classes中

image.png

31.getLoadMethod函数拿到所有类的load方法

image.png

32.递归调用load函数

image.png

33.断点看C++函数的调用栈

image.png

34.doInitialization函数是在recursiveInitialization函数中

35.上面的执行完毕之后执行main函数,在dyld_start中

image.png

最后整理下流程图 image.png