先说下Mach-O文件:
Mach-O文件格式是 OS X 与 iOS 系统上的可执行文件格式,像我们编译过程产生的.O文件,以及程序的可执行文件,动态库等都是Mach-O文件。它的结构如下:

有如下几个部分组成:
Header:保存了一些基本信息,包括了该文件运行的平台、文件类型、LoadCommands的个数等等。
LoadCommands:可以理解为加载命令,在加载Mach-O文件时会使用这里的数据来确定内存的分布以及相关的加载命令。比如我们的main函数的加载地址,程序所需的dyld的文件路径,以及相关依赖库的文件路径。
Data: 这里包含了具体的代码、数据等等。
我们可以通过Mach-O文件查看器MachOView查看一个测试项目(这里放上地址)编译后的可执行文件内容:

这里可以看到,程序需要的dyld的路径在LC_LOAD_DYLINKER命令里,一般都是在/usr/lib/dyld 路径下。这里的LC_MAIN指的是程序main函数加载地址,下面还有写LC_LOAD_DYLIB指向的都是程序依赖库加载信息,如果我们程序里使用到了AFNetworking,这里就会多一条名为LC_LOAD_DYLIB(AFNetworking)的命令,如下图

这里可以看到一些我们比较常用的三方库:AFNetworking,IQKeyboard等。
系统加载程序可执行文件后,通过分析文件来获得dyld所在路径来加载dyld,然后就将后面的事情甩给dyld了。
dyld
dyld: (the dynamic link editor)动态链接器,其源码是开源的。
主要负责初始化程序环境,将可执行文件以及相应的依赖库与插入库加载进内存生成对应的ImageLoader类的image(镜像文件)对象,对这些image进行链接,调用各image的初始化方法等等(注:这里多数事情都是递归的,从底向上的方法调用),其中runtime也是在这个过程中被初始化
main函数被调用
当所有的依赖库库的lnitializer都调用完后,dyld::main函数会返回程序的main函数地址,main函数被调用,从而代码来到了我们熟悉的程序入口。