苹果在 iOS16
之后运用 dyld4
取代了 dyld3
, 可是目前网上的资料都是介绍dyld3发动流程, 本文讲解最新的dyld4的原理和中心流程
官网dyld4介绍 github.com/apple-oss-d…
dyld4
dyld(the dynamic link editor)是苹果的动态链接器
,是苹果操作体系一个重要组成部分,在体系内核 XNU 完结 Mach-O 文件的加载,做好程序准备作业之后,交由 dyld 担任余下的作业如动态库加载, 进程信息初始化。
dyld 最新版本是dyld4
dyld4
一起支持pre-built loader
(提早缓存) 来提高发动速度
也支持 just-in-time loader
(实时加载)来应对App或体系信息
改变的情况
发动
内核将一切KernelArgs
(内核参数)推送到堆栈上并跳转到 dyld 的入口点start()
来发动进程。
void start(const KernelArgs* kernArgs, void* prevDyldMH)
KernelArgs(内核参数)
KernelArgs
指向内核在堆栈上传递给 dyld 信息的指针(例如 argc
、argv
、envp
和apple parameter
等)。
进程状况
分为两类
-
DyldProcessConfig
保存进程的
固定
状况信息(例如安全策略,dyld缓存,日志记录标志,平台等)。 -
DyldRuntimeState
保存在进程生命周期内
改变
的状况信息。它包括Loader、注册的告诉函数和一切锁。
Loader objects
每个加载的 mach-o
文件(可履行程序, 动态库) 对应一个 dyld4::Loader
目标盯梢。
分为如下四类mach-o
- 可履行程序
- libsystem.dylib
- libdyld.dylib
- 其他dylib
// Loader 加载器(Prebuilt or JustInTime 两种 loader)
const Loader* mainExecutableLoader = nullptr; // 主程序加载办法
Vector<ConstAuthLoader> loaded; // 其他动态库加载办法
const Loader* libSystemLoader = nullptr; // libsystem.dylib 加载办法
const Loader* libdyldLoader = nullptr; // libdyld.dylib 加载办法
Loader
运用 loadAddress()
来获取 mach_o
信息 .
Loader 有两种
- PrebuiltLoader: 运用 dyld cache和缓存文件, 速度更快。
- JustInTimeLoader: 速度慢, 可是更新及时
PrebuiltLoader
包括 mach-o 文件的预先核算
(缓存
)的信息,包括途径、验证信息、依靠的 dylib 和预先核算的绑定方针数组。
PrebuiltLoaderSet
一个进程中最多有两个 PrebuiltLoaderSet
- 一个在 dyld 缓存中,包括
每个 dylib
的PrebuiltLoader,该 dylib 是 dyld 同享缓存的一部分。 - 另一个是
App
的PrebuiltLoaderSet, 包括mainLoader- App的PrebuiltLoaderSet来自两个方位:
dyld 缓存或文件
。
- App的PrebuiltLoaderSet来自两个方位:
JustInTimeLoader
JustInTimeLoader 经过MachOAnalyzer
根据需要实时解析mach-o文件。
加载一切images之后,dyld 将 JustInTimeLoader 目标“克隆”到 PrebuiltLoader 目标,然后将这些目标打包到 PrebuiltLoaderSet 中并写入磁盘, 之后就可以运用 PrebuiltLoader 加载缓存了,提高了App运转速度。
App Loader 进程
- 发动时,dyld 查找 PrebuiltLoader, 假如找到,则调用其 isValid()判断有用, 则运用Prebuilt。
- 假如没有,则创立一个新 JustInTimeLoader, JustInTimeLoader 经过解析 mach-o 来查找其依靠项。
- 对于每个依靠项,都会履行上面相同的过程。
SyscallDelgate
SyscallDelgate 处理一切syscal(如翻开或映射文件)。
- 初级(即posix级)办法: 如翻开,封闭,mmap。
- 更高级别的办法: withReadOnlyMappedFile等