iOS 底层探索篇 —— dyld加载流程(下)

1 dyld加载流程分析(下)

上文说到_objc_init中调用了_dyld_objc_notify_register(&map_images, load_images, unmap_image)对registerObjCNotifiers中的sNotifyObjCMappedsNotifyObjCInitsNotifyObjCUnmapped,进行了赋值。那么sNotifyObjCMapped,sNotifyObjCInit是在哪里调用的呢

1.1 sNotifyObjCMapped 的调用

在dyld 源码中搜索sNotifyObjCMapped,看到其在notifyBatchPartial中被调用。
在这里插入图片描述
在搜索notifyBatchPartial在哪里被调用,发现其在被赋值后就直接被调用了
在这里插入图片描述

1.2 sNotifyObjCInit 的调用

在dyld 源码中搜索sNotifyObjCInit,发现也是赋值后,sNotifyObjCMapped调用之后调用
在这里插入图片描述

1.3 load 函数的调用

load函数是哪里调用的呢?在load函数打个断点,然后输入bt查看,发现是在load_images里面。
在这里插入图片描述
那么load_images 又是如何调用的load函数呢。 首先找到load_images,看到这里有一个prepare_load_methods
在这里插入图片描述
点击进去看到prepare_load_methods有主类和分类的load方法
在这里插入图片描述
先看主类的load 方法,看到这里会进行递归,将类的所有父类也调用schedule_class_load方法。然后会add_class_to_loadable_list
在这里插入图片描述
点进去看到有getLoadMethod
在这里插入图片描述
在点进去看到这里将类中的load方法imp取了出来
在这里插入图片描述
在看回getLoadMethod,发现其将class 添加到loadable_classes里面,这里的method就是之前返回的load 方法的imp

再来看分类的load方法发现实现差不多,只是添加到了另一个字典loadable_categories里面。
在这里插入图片描述
再回到load_images 方法,看到有call_load_methods方法。
在这里插入图片描述
看到call_load_methods里面有call_class_loadscall_category_loads方法。这里做的就是递归将所有的loadable_classes里面的类和loadable_categories里面的分类的load方法进行调用
在这里插入图片描述
看一下call_class_loads,发现确实是将loadable_classes里面的class和method取出来,然后进行load方法的调用。
在这里插入图片描述
看一下分类的实现方法,也是一摸摸一样样的。
在这里插入图片描述

1.4 CXX 方法的调用

在main函数中添加一个CXX 方法。
在这里插入图片描述
运行后发现,是在load方法之后。
在这里插入图片描述
在CXX 方法里面打个断点,然后输入bt查看方法栈,发现是在doModInitFunctions里面调用的。
在这里插入图片描述
doModInitFunctions是在doInitialization里面调用的,而doInitialization是在notify之前,也就是load方法之前的,为什么这里反而cxx方法在load之后调用呢?这里因为这里的doInitialization是objc的镜像文件初始化,而不是工程的初始化,所以工程里的cxx方法在load后面调用。证明一下,在_objc_init中添加cxx方法。
在这里插入图片描述
然后运行,可以看到在_objc_init中的c++函数确实是在load方法之前的。
在这里插入图片描述

1.5 main 函数的调用

dyld是如何找到main函数并对其进行调用的呢? 又回到最初的起点:dyld_start。看到这里的最后一行有一个跳转到main函数的地方。
在这里插入图片描述
在mac上运行一下证明,在cXX函数打个断点,然后进入汇编模式
在这里插入图片描述
往下走,看到jmpq *%rax,也就是之前说会跳转到main函数的地方。
在这里插入图片描述
读取一下寄存器,发现rax就是main函数。所以jmpq *%rax 也就是调用main函数。
在这里插入图片描述
如果把main函数名字改成别的,那么还能进行调用吗?
在这里插入图片描述
运行一下,发现了报错。可以知道main是写定的函数,写入内存,读取到dyld,如果修改了main函数的名称,那么程序就会报错。
在这里插入图片描述

1.6 dyld流程图

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值