iOS

认识 dyld :动态链接器

2022-03-23  本文已影响0人  _涼城

什么是 dyld

    dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统一个重要组成部分,在系统内核 XNU 完成 Mach-O 文件的加载,做好程序准备工作之后,交由 dyld 负责余下的工作。在 macOS 系统中,dyld 位于 D/usr/lib/dyld
    dyld Github源码地址

dyld 1.0 (1996–2004)

dyld 2 (2004-2017)

执行流程

dyld2

加载共享缓存

    因为 Foundation 还会依赖一些其他动态库,这些依赖的其他库还会再依赖更多的库,所以相互依赖的符号会很多,需要处理的时间也会比较长。这里系统上的动态链接器会使用共享缓存,共享缓存在 /var/db/dyld/。当加载 Mach-O 文件时,动态链接器会先检查是否有共享缓存。每个进程都会在自己的地址空间映射这些共享缓存,这样做可以起到优化 App 启动速度的作用。

动态库加载

    链接的共用库分为静态库和动态库:

    Mach-O 文件是编译后的产物,而动态库在运行时才会被链接,并没参与 Mach-O 文件的编译和链接,所以 Mach-O 文件中并没有包含动态库里的符号定义。也就是说,这些符号会显示为“未定义”,但它们的名字和对应的库的路径会被记录下来。运行时通过 dlopendlsym 导入动态库时,先根据记录的库路径找到对应的库,再通过记录的名字符号找到绑定的地址。

     dlopen 会把共享库载入运行进程的地址空间,载入的共享库也会有未定义的符号,这样会触发更多的共享库被载入。dlopen 也可以选择是立刻解析所有引用还是滞后去做。dlopen 打开动态库后返回的是引用的指针,dlsym 的作用就是通过 dlopen 返回的动态库指针和函数符号,得到函数的地址然后使用。

dyld 2 存在的问题

Tips : -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null 虽然在 iOS 10 以前才可以避免动态库的注入,但是可以通过修改 Mach-O 绕过

Tips : 一般情况下,动态库的路径都是 @rpath ,比如: @excutable/Frameworks

dyld 3 (2017)

     dyld 3是全新的动态链接器,它完全改变了动态链接概念WWDC-App Startup Time: Past, Present, and Future 提到在iOS 13系统中,iOS 全面采用新的 dyld 3 以替代之前版本的 dyld 2dyld 3带来了可观的性能提升,减少了APP的启动时间。 因为 dyld 3 完全兼容 dyld 2,API 接口是一样的,所以在大部分情况下,开发者不需要做额外的适配就能平滑过渡。

执行流程

dyld3-process
dyld 3 包含这三个部分:

    大多数程序启动会使用缓存,而不需要调用进程外 mach-o分析器或编译器;并且 launch closureMach-O 更简单,它们是内存映射文件,不需要用复杂的方法进行分析,我们可以简单地验证它们,其作用是为了提高速度

dyld 3的符号缺失问题

     dyld 2 默认采取的是 lazy symbol 的符号加载方式,但在 dyld 3中,在 App 启动之前,符号解析的结果已经在 lauch closure 内了,所以 lazy symbol 就不再需要。这时,如果有符号缺失的情况,APP 的行为会有不同:在 dyld 2 中,首次调用缺失符号时 APP 会 crash;而 dyld 3 中,缺失符号会导致 APP 一启动就会 crash。

dyld 4 (2022)

上一篇下一篇

猜你喜欢

热点阅读