美文网首页
iOS【Mach-O可执行文件】

iOS【Mach-O可执行文件】

作者: NJ_墨 | 来源:发表于2020-05-30 15:44 被阅读0次

    摘录:其字德安「Mach-O文件结构」
    (以此记录一下)

    iOS上的可执行文件相当于windows上的.exe可执行文件。
    在iOS上,主要的可执行文件格式是Mach-O格式。

    iOS程序包是.ipa文件。解压缩后里面会有一个payload文件夹,文件夹里有一个.app文件,右键显示包内容,然后找到一个一般体积最大跟.app同名的文件,那个文件就是可执行文件。

    Mach-O类型的文件

    • Mach-O是一种文件的格式; 是iOS/Mac OS上存储程序以及库的标准格式

      • Mach Object
    • Mach-O格式的文件

    #define MH_OBJECT   0x1     /* 目标文件*/
    #define MH_EXECUTE  0x2     /* 可执行文件 */
    #define MH_FVMLIB   0x3     /* fixed VM shared library file */
    #define MH_CORE     0x4     /*核心转储文件 */
    #define MH_PRELOAD  0x5     /* preloaded executable file */
    #define MH_DYLIB    0x6     /* dynamically bound shared library */
    #define MH_DYLINKER 0x7     /* dynamic link editor */
    #define MH_BUNDLE   0x8     /* dynamically bound bundle file */
    #define MH_DYLIB_STUB   0x9     /* shared library stub for static */
                        /*  linking only, no section contents */
    #define MH_DSYM     0xa     /* companion file with only debug */
                        /*  sections */
    #define MH_KEXT_BUNDLE  0xb     /* x86_64 kexts */
    
    

    常见的Mach-O格式的文件

    1、`MH_OBJECT` 目标文件
        *`.o`
        *`.a/ .framework`静态库
            *静态库即多个`.o`文件存放在一起实现特定的功能
    
    2、`MH_EXECUTE` 可执行文件
        *`.app/MyApp`
        *`.out`
    
    3、  `MH_DYLIB` 动态库
        *`.framework/xxx`
        *`/dylib`
    
    4、`MH_DYLINKER` 动态链接器
        *`usr/lib/dyld`
    
    5、`MH_DSYM` 存储二进制文件符号信息的文件
        *`.dYSM/Contents/Resources/DWARF/MyApp`
    

    如图:


    image

    查看项目targetMach-O文件的类型
    MH_EXECUTE类型
    如图:

    image

    Mach-O文件的基本结构

    Mach-O包含三个主要区域

    1、`Header`: 文件类型, 目标架构
    2、`Load command`: 描述文件在虚拟内存中的逻辑与布局
    3、`Raw segment date`: `Load command`中定义的原始数据
    
    image
    • 使用otool查看Mach-O文件
    ➜ otool -h  DingTalk
    Mach header
          magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
     0xfeedface      12          9  0x00           2    79       7860 0x00218085
    Mach header
          magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
     0xfeedfacf 16777228          0  0x00           2    79       8672 0x00218085
    
    
    • 使用file查看Mach-O文件
    # 该Mach-O文件类型是 executable  只有armv7指令集
    ➜  HomeDesign3D China.app file HomeDesign3D\ China
    HomeDesign3D China: Mach-O executable arm_v7
    
    # 该Mach-O文件 类型是 executable;  有armv7, arm64指令集是一个通用二进制文件
    ➜  DingTalk.app file DingTalk
    DingTalk: Mach-O universal binary with 2 architectures: [arm_v7: Mach-O executable arm_v7] [arm64]
    DingTalk (for architecture armv7):  Mach-O executable arm_v7
    DingTalk (for architecture arm64):  Mach-O 64-bit executable arm64
    
    
    • 通用二进制文件

      • universal binary或者Fat binary

      • 含有多个不同架构的独立二进制文件; 故体积较大

      • 执行时, 只会选择一种架构的二进制文件

      image
    • 使用MachOView查看Mach-O文件

      • 以查看DingTalk为例
    image image image
    • RAWRVA
      RV: 虚拟地址
      RAW: 文件偏移地址(物理地址)
      RVA: 相对虚拟地址的偏移

    Mach-O结构详解

    Mach Header(arm64)
    • Magic Number : 魔数, 表示支持设备的CPU位数

      • oxFEEDFACE : 表示32位二进制

      • oxFEEDFACF : 表示64位二进制

    • cputypecpusubtype: CPU类型和子类型

    • filetype : Mach-O文件类型

    • ncmdssizeofcmds: 用于加载器的 加载命令的条数和大小

    • flags : 动态链接器dyld的标志

    image

    LC_SEGMENT / LC_SEGMENT_64段的详解

    • 常见段

      __PAGEZERO: 空指针陷阱段
      _TEXT: 程序代码段
      __DATA: 程序数据段
      __RODATA: read only程序只读数据段
      __LINKEDIT: 链接器使用段

    image
    • section段常见字段

      Segment Name: 该Segment的名称, 用于load_segment
      VM Address: 该段的虚拟物理地址
      VM Size: 该段所需要分配的虚拟内存大小(字节)
      File Offset: 该段在文件中的偏移量
      File Size: 该段在文件中占据的字节数
      Maximum VM Protection: 段的页面所需要的最高内存保护

      ox1: x 执行
      ox2: w 写
      0x4: r 读

      Initial VM Protection: 段页面初始化的内存保护
      Number of Sections: 段中section区的数量
      Flags: 其他标志位

    段中区section详解

    • 常见区section

      __text: 主程序代码
      __stubs, __stub_helper: 用于动态链接的桩
      __cstring: 程序中c语言字符串

      __const: 常量

      __RODATA,__objc_methname: OC方法名称
      __RODATA,__objc_methntype: OC方法类型
      __RODATA,__objc_classname: OC类名

      __DATA,__objc_classlist: OC类列表
      __DATA,__objc_protollist: OC原型列表
      __DATA,__objc_imageinfo: OC镜像信息

      __DATA,__objc_const: OC常量
      __DATA,__objc_selfrefs: OC类自引用(self)
      __DATA,__objc_superrefs: OC类超类引用(super)
      __DATA,__objc_protolrefs: OC原型引用
      __DATA, __bss: 没有初始化和初始化为0 的全局变量

    image

    Load Commmands加载命令中其他信息

    • 加载动态链接器
      LC_LOAD_DYLINKER: 内核执行该命令时, 启动dyld

    • 获取符号表
      LC_SYMTAB: 符号地址表
      LC_DYSYMTAB: 动态符号地址表

    • 加载动态库
      LC_LOAD_WEAK_DYLIB
      LC_LOAD_DYLIB

    动态库加载流程小结
    1.0 首先启动dyld动态链接器; 内核根据LC_LOAD_DYLINKER启动/usr/lib/dyld

    2.0 如果Mach-O文件中使用了外部定义的符号或函数, 则会在文本段__TEXT有__stubs, __stub_helper区; 区内放着本地未被定义的符号; 编译器在编译源码时会创建对这些未定义符号桩区的调用

    3.0 dyld运行时, 会在符号桩区调用地址上; 添加JMP 到 真实函数地址的指令

    4.0 至于dyld怎么找到指定的动态库中指定的函数地址? 此时dyld将加载Load Command中的LC_LOAD_DYLIB命令

    5.0 LC_LOAD_DYLIB(动态库), dyld将加载每一个指定的库且搜寻匹配的符号

    6.0 当符号匹配时, 将在符号表(由dyld加载LC_SYMTAB, LC_DYSYMTAB获取)查找对应的函数/符号地址

    相关文章

      网友评论

          本文标题:iOS【Mach-O可执行文件】

          本文链接:https://www.haomeiwen.com/subject/wsnczhtx.html