一、应用程序加载原理
在分析dyld
加载应用程序之前,先清楚以下基本概念。
库:可执行的二进制文件,可以被系统加载到内存。库分为静态库和动态库,动态和静态库的区别是链接的区别。
编译过程
源文件->预编译->编译->汇编->链接->可执行文件(MachO
格式)。
动态库:动态链接。只会存在一份,在内存中共享。减少了包的体积大小。这里有完全动态特性的就是系统的动态库了。
静态库:静态链接。静态库在装载的时候会重复,浪费了空间。
那么这些库是怎么加载到内存中的呢?
是通过dyld
动态链接器加载到内存中的。整个过程大概如下:
dyld
(the dynamic link editor
)动态链接器,是苹果操作系统一个重要组成部分,在系统内核做好程序准备工作之后交由dyld
负责余下的工作。
这篇文章将详细分析整个dyld
加载过程。
二、dyld 初探
既然是dyld
加载的库,那么在加载完成后肯定会进入main
函数,那么在main
函数上打个断点看下调用:
可以看到是libdyld.dylib start:
调用的main
函数。给start
下个符号断点并没有进入断点。那么证明在底层的符号不是start
。实现一个+ load
方法打个断点发现如下调用栈:
可以看到是dyld _dyld_start
发起的调用。opensoure
上直接下载dyld-852
源码。
搜索_dyld_start
发现这个入口是在汇编中,其中主要是调用了dyldbootstrap::start
:
最终跳转了返回的LC_MAIN
。
也可以通过断点查看汇编调用确定:
dyldbootstrap
是c++
的命名空间,start
是其中的函数。搜索后发现dyldbootstrap::start
在dyldInitialization.cpp
中,这也就是函数开始的地方。接下来结合源码分析怎么从start
调用到load
和main
方法,以及dyld
是如何加载images
的。