Mach-O学习笔记

Mach-O文件结构

image.png
  • Header部分:描述文件基本信息(如CPU、架构、文件类型、加载命令个数)
    Mach-O学习笔记_第1张图片
  • loadCommands部分:描述各个Data部分的内存分布,对系统内核加载器和动态连接器起指导作用
    Mach-O学习笔记_第2张图片
  • Data部分:存放代码与数据

    • __PAGEZERO段:空指针陷阱段,映射到虚拟内存空间的第一页,用于捕捉对NULL指针的引用
    • __TEXT 段: 包含了执行代码以及其他只读数据的,当这个段被映射到内存后,可以被所有进程共享。(这主要用在frameworks, bundles和共享库等程序中,也可以为同一个可执行文件的多个进程拷贝使用)
    section 描述
    __text 代码实现
    __stubs 符号桩,本质上就是段会直接跳入到lazybinding的表的对应项指针指向的地址的代码
    __stubs_helper 辅助函数,上述lazybinding表中没有找到符号地址都指向这
    __cstring C string字符串常量
    __ustring Unicode string中文常量
    __objc_methname OC方法名称
    __objc_classname OC类名
    __objc_methtype OC方法类型
    __entitlements 签名证书
    __unwid_info 用于存储异常情况信息
    __const 初始化的常量
    • __DATA段: 包含了程序数据,该段可写;
    section 描述
    __const 未始化的常量
    __bss 没有初始化和初始化为0 的全局变量
    __nl_symbol_prt / __got 非lazy-binding的指针表
    __la_symbol_prt lazy-binding的指针表,每个表项中的指针一开始指向stub_helper
    __cfstring CoreFoundation string
    __objc_classlist OC类列表
    __objc_catlist OC分类列表
    __objc_protollist OC协议列表
    __objc_imageinfo OC镜像信息
    __objc_const OC类信息、方法列表、属性列表、变量列表
    __objc_selfrefs OC类实例自引用(self)
    __objc_classfrefs OC类类自引用
    __objc_superrefs OC类超类引用(super)
    __objc_ivar OC属性
    __objc_data OC类ISA
    • __LINKEDIT段: 含有为动态链接库使用的原始数据,比如符号,字符串,重定位表条目等等。

App启动流程

Mach-O学习笔记_第3张图片
  1. 将Mach-O中Segment与符号表等数据映射到内存中
  2. 调用dyld(the dynamic link editor)程序,动态链接器
  3. 加载UUID与构建二进制是的的源码版本等信息
  4. 设置程序主线程的main函数入口地址和栈大小
  5. 设置依赖的动态库
  6. 加载代码开始地址、代码段内的非指令的表、代码签名
  7. 系统kernel做好启动程序的初始准备后,动态链接依赖库,并由runtime负责加载成objc定义的结构,所有初始化工作结束后,dyld调用真正的main函数
    1. 从kernel留下的原始调用栈引导和启动自己

    2. 将程序依赖的动态链接库递归加载进内存,系统有缓存机制

      1. 交由imageLoader读取image,其中包含了我们的类,方法等各种符号
      2. 由于runtime向dyld绑定了回调,当image加载到内存后,dyld会通知runtime进行处理
      3. runtime接手后调用map_images做解析和处理,接下来load_images中调用call_load_methods方法,遍历所有加载进来的Class,按继承层级依次调用Class的+load方法和Category的+load方法
    3. non-lazy符号立即link到可执行文件,lazy的存表里

    4. 找到可执行文件的main函数,准备参数并调用

    5. 程序执行中负责绑定lazy符号、提供runtime dynamic loading services、提供调试器接口。

    6. 程序main函数return后执行static terminator

    7. 某些场景下main函数结束后调libSystem的_exit函数。

参考

  • dyld源码
  • iOS 程序 main函数之前发生什么
  • Mach-O文件介绍之loadcommand

你可能感兴趣的:(Mach-O学习笔记)