[TOC]
总结回顾
1:类的加载 – 协议 属性 ro – rw 慢速流程 – 懒加载 – 非懒加载
2:map_images() 什么时候加载
3:load_images() load方法的集合 – cxx + load + main
4:dyld -> main
5:wwdc2017关于dyld2 vs dyld3的一些改变 优化的点 launchclusure避免了一些闭包模式的加载
苹果2020 WWDC 关于Runtime的优化 developer.apple.com/videos/play…
coreFoudation源码: opensource.apple.com/tarballs/CF…
Dyld 拓展补充 WWDC2017 developer.apple.com/videos/play…?
wwdc2017关于dyld2 vs dyld3的一些改变 优化的点 launchclusure避免了一些闭包模式的加载
dyld:developer.apple.com/videos/play…
dyld链接objc的函数执行
dyld如何连接 镜像文件和反向回调
objc源码中 _objc_init() 方法 调用 _dyld_objc_notify_register(&map_images, load_images, unmap_image);
对于&map_images, load_images 如何调用 沟通了objc和dyld的流程 要进行探索
在dyld源码中 _dyld_objc_notify_register( 方法 调用 registerObjCNotifiers(
void registerObjCNotifiers(_dyld_objc_notify_mapped mapped, _dyld_objc_notify_init init, _dyld_objc_notify_unmapped unmapped)
{
// record functions to call
sNotifyObjCMapped = mapped;
sNotifyObjCInit = init;
sNotifyObjCUnmapped = unmapped;
// call 'mapped' function with all images mapped so far
try {
notifyBatchPartial(dyld_image_state_bound, true, NULL, false, true);
}
catch (const char* msg) {
// ignore request to abort during registration
}
// <rdar://problem/32209809> call 'init' function on all images already init'ed (below libSystem)
for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
ImageLoader* image = *it;
if ( (image->getState() == dyld_image_state_initialized) && image->notifyObjC() ) {
dyld3::ScopedTimer timer(DBG_DYLD_TIMING_OBJC_INIT, (uint64_t)image->machHeader(), 0, 0);
(*sNotifyObjCInit)(image->getRealPath(), image->machHeader());
}
}
}
复制代码
registerObjCNotifiers( 方法中有三个重要的赋值
sNotifyObjCMapped = mapped; //map_images()方法加载
sNotifyObjCInit = init; //load_images()方法加载
sNotifyObjCUnmapped = unmapped;
复制代码
map_images
sNotifyObjCMapped方法 搜索发现 在方法里面调用
try {
notifyBatchPartial(dyld_image_state_bound, true, NULL, false, true);
}
复制代码
load_images
sNotifyObjCInit方法
递归流程
load和cxx和main调用流程
main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
NSLog(@"1223333");
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
__attribute__((constructor)) void kcFunc(){
printf("来了 : %s \n",__func__);
}
复制代码
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
+ (void)load{
NSLog(@"%s",__func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
@end
复制代码
结果 1.load 2.c++ 3.main
+[ViewController load]
来了 : lrFunc
1223333
复制代码
load方法调用探索 load_images() 方法
所有load方法
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
load_images(
准备load方法 调用load方法
1.prepare_load_methods((const headerType *)mh);//准备load方法
准备分为 本类load方法 分类的load方法
2.call_load_methods();//调用load方法
调用也分为 本类load方法 分类的load方法
准备load方法 prepare_load_methods((const headerType *)mh);
prepare_load_methods(
1.schedule_class_load(remapClass(classlist[i]));//调度类的load方法
2.add_category_to_loadable_list(cat);//调用分类的load方法
先调用类的load方法 后调用分类的load方法
以类的load方法收集为例 探索, 分类的load方法收集过程相似
schedule_class_load(
add_class_to_loadable_list(
objc_class::getLoadMethod()
调用load方法 call_load_methods();
调用也是 本类load方法 分类的load方法
call_class_loads();
call_category_loads();
c++方法调用探索
为什么c++方法会自动调用?
bt堆栈调试
recursiveInitialization -> doInitialization -> doModInitFunctions -> libSystem_initializer -> libdispatch_init -> _os_object_init -> _objc_init
在这个调用流程上
查阅源码
context.notifySingle(dyld_image_state_dependents_initialized, this, &timingInfo); 方法是load方法的调用
doInitialization 方法是c++主动调用的点
doModInitFunctions方法 读取cmd_count 即mach-O里面的东西,
main函数调用探索
最后至于main函数如何调用 __dyld_start之后
打开汇编 在lrFunc 这个c++方法里面添加断点进行单步调试
单步过掉 load 和 c++方法之后 就到了main方法
此时读取寄存器 register read,会发现main函数在这里, 即main函数调用了