zoukankan      html  css  js  c++  java
  • MachO文件基础

    Mach-O(Mach Object File Format,wikichs)是macOS、iOS、iPadOS上的可执行文件格式,类似于 Linux(UNIX )的ELF以及 Windows 上的PE。

    具体格式包括:*.a(静态库) 、*.dylib(动态库)、可执行文件、*.o(中间文件)、*.dSYM(调试符号)。一个Mach-O文件中,可以包含多个架构(如同时包含armv7、arm64)。

    file ./Test1  // 通过file命令来查看当前目录可执行二进制Test1的架构信息

    admin@NICOCHEN-MC4 Test1.app % file Test1
    Test1: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64:Mach-O 64-bit executable arm64]
    Test1 (for architecture armv7):    Mach-O executable arm_v7
    Test1 (for architecture arm64):    Mach-O 64-bit executable arm64

    otool -f -V ./Test1 // 通过otool命令查看当前目录可执行二进制Test1的架构信息

    Fat headers
    fat_magic FAT_MAGIC
    nfat_arch 2
    architecture armv7
        cputype CPU_TYPE_ARM
        cpusubtype CPU_SUBTYPE_ARM_V7
        capabilities 0x0
        offset 16384
        size 79488
        align 2^14 (16384)
    architecture arm64
        cputype CPU_TYPE_ARM64
        cpusubtype CPU_SUBTYPE_ARM64_ALL
        capabilities 0x0
        offset 98304
        size 80208
        align 2^14 (16384)

    设置Test1的Architectures为armv7和arm4,目标设备设置为Any iOS Device(armv7, arm64)

    /Users/admin/Library/Developer/Xcode/DerivedData/Test1-enpnmzugwpjxckbyiyimrjuwqjqk/Build/Products/Debug-iphoneos/Test1.app   注:Xcode输出路径在Preferences面板的Locations标签中指定

    lipo -thin armv7 ./Test1 -o Test1_v7  // 将当前目录中Test1的armv7架构保存到独立的Test1_v7可执行文件中  注:Test1_v7的架构仅包含armv7

     

    MachO文件结构(以UAGame的shipping版iOS可执行文件为例)

    字段说明

    字段 含义
    Mach64 Header

    描述了 Mach-O 的魔数、CPU 架构、文件类型以及加载命令(Load Commands)等信息

    注:魔数为MH_MAGIC_64表示大端序,为MH_CIGAM_64表示小端序

    Load Commands load commands会指导动态加载器(dyld)该如何加载Mach-O文件
    __PAGEZERO Catch访问NULL指针的非法操作的段
    __TEXT 为代码段、只读数据段
    __DATA 可读写数据段
    LC_LOAD_DYLINKER 指定了dyld所在的路径为/usr/lib/dyld
    LC_UUID 记录了当前MachO文件的uuid值
    LC_VERSION_MIN_IPHONEOS 最小可运行的iphone os版本
    LC_MAIN

    main函数地址(entry point)

    LC_LOAD_DYLIB 类似于强引用当前库。如果无法成功load当前库,就会报错,导致启动失败
    LC_LOAD_WEAK_DYLIB 类似于弱引用,如果加载路径下有这个库,就引入;否则可以不引入。不影响使用
    LC_SYMTAB

    指向symbol table和string table。symbol table包含了可执行的镜像文件所用到的所有符号信息。

    注:符号名在symbol table只存了一个string index索引值,具体的字符串存放在string table中。

    LC_DYSYMTAB

    指向indirect symbol table,为一个index 数组,即每个条目的内容是一个 index 值,该index 值(从 0 开始)指向到symbol table中的条目。

    该表是为__stubs、__nl_symbol_ptr、__got、__la_symbol_ptr段服务的

    Indirect symbols for (__TEXT,__stubs) 1 entries
    address index
    0x0000000000001fbe 3

    Indirect symbols for (__DATA,__nl_symbol_ptr) 2 entries
    address index
    0x0000000000002000 4

    0x0000000000002008 ABSOLUTE

    Indirect symbols for (__DATA,__got) 1 entries
    address index
    0x0000000000002010 2

    Indirect symbols for (__DATA,__la_symbol_ptr) 1 entries
    address index
    0x0000000000002018 3

    可通过otool -I ./UAGame-IOS-Shipping命令来查看其内容

     

    otool -L ./UAGame-IOS-Shipping // 查看可执行文件UAGame-IOS-Shipping依赖的第三方动态链接库  注:该命令会读取LC_LOAD_DYLIB和LC_LOAD_WEAK_DYLIB的信息

    ./UAGame-IOS-Shipping:
        /System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
        /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 5067.3.107)
        /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1854.0.0)
        /System/Library/Frameworks/AudioToolbox.framework/AudioToolbox (compatibility version 1.0.0, current version 1000.0.0)
        /System/Library/Frameworks/AVFoundation.framework/AVFoundation (compatibility version 1.0.0, current version 2.0.0)
        /System/Library/Frameworks/GameKit.framework/GameKit (compatibility version 1.0.0, current version 810.63.3)
        /System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreVideo.framework/CoreVideo (compatibility version 1.2.0, current version 1.5.0)
        /System/Library/Frameworks/CoreMedia.framework/CoreMedia (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 1548.1.3)
        /System/Library/Frameworks/GameController.framework/GameController (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 1163.10.2)
        /System/Library/Frameworks/DeviceCheck.framework/DeviceCheck (compatibility version 1.0.0, current version 1.0.0, weak)
        /System/Library/Frameworks/UserNotifications.framework/UserNotifications (compatibility version 1.0.0, current version 1.0.0, weak)
        /System/Library/Frameworks/CoreMotion.framework/CoreMotion (compatibility version 1.0.0, current version 2663.0.3)
        /System/Library/Frameworks/AdSupport.framework/AdSupport (compatibility version 1.0.0, current version 1.0.0, weak)
        /System/Library/Frameworks/WebKit.framework/WebKit (compatibility version 1.0.0, current version 612.1.27)
        /System/Library/Frameworks/iAd.framework/iAd (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreAudio.framework/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreTelephony.framework/CoreTelephony (compatibility version 1.0.0, current version 0.0.0)
        /System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 60157.12.1)
        /System/Library/Frameworks/CFNetwork.framework/CFNetwork (compatibility version 1.0.0, current version 1312.0.0)
        /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 612.1.27)
        /System/Library/Frameworks/CoreText.framework/CoreText (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreImage.framework/CoreImage (compatibility version 1.0.0, current version 5.0.0)
        /System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/Accelerate.framework/Accelerate (compatibility version 1.0.0, current version 4.0.0)
        /System/Library/Frameworks/VideoToolbox.framework/VideoToolbox (compatibility version 1.0.0, current version 1.0.0, weak)
        /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 1141.1.0)
        /System/Library/Frameworks/EventKit.framework/EventKit (compatibility version 1.0.0, current version 1716.0.0)
        /System/Library/Frameworks/Photos.framework/Photos (compatibility version 1.0.0, current version 402.5.140)
        /System/Library/Frameworks/MediaPlayer.framework/MediaPlayer (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/MapKit.framework/MapKit (compatibility version 1.0.0, current version 14.0.0)
        /System/Library/Frameworks/CoreLocation.framework/CoreLocation (compatibility version 1.0.0, current version 2663.0.3)
        /System/Library/Frameworks/CoreData.framework/CoreData (compatibility version 1.0.0, current version 1132.0.0)
        /System/Library/Frameworks/EventKitUI.framework/EventKitUI (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/MessageUI.framework/MessageUI (compatibility version 1.0.0, current version 3693.0.2)
        /System/Library/Frameworks/Social.framework/Social (compatibility version 1.0.0, current version 87.0.0)
        /System/Library/Frameworks/Metal.framework/Metal (compatibility version 1.0.0, current version 257.25.0, weak)
        /System/Library/Frameworks/OpenAL.framework/OpenAL (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/OpenGLES.framework/OpenGLES (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/MediaToolbox.framework/MediaToolbox (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/AdServices.framework/AdServices (compatibility version 1.0.0, current version 1.0.0, weak)
        /System/Library/Frameworks/AppTrackingTransparency.framework/AppTrackingTransparency (compatibility version 1.0.0, current version 1.0.0, weak)
        /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
        /usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 329.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1200.3.0)
        /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
        /usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
        /usr/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.9.0)
        /usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.8)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0)
        /System/Library/Frameworks/AVKit.framework/AVKit (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1854.0.0)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

    注:framework并不是库,它只是一种打包方式,里面既可以是动态库也可以是静态库。它将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。

    xcrun size -lm UAGame-IOS-Shipping // 查看可执行文件UAGame-IOS-Shipping各段的size、起始地址和offset信息

    Segment __PAGEZERO: 4294967296 (zero fill)  (vmaddr 0x0 fileoff 0)
    Segment __TEXT: 140509184 (vmaddr 0x100000000 fileoff 0)
        Section __text: 123041436 (addr 0x100004000 offset 16384)
        Section __stubs: 96420 (addr 0x10755b69c offset 123057820)
        Section __stub_helper: 17496 (addr 0x107572f40 offset 123154240)
        Section __gcc_except_tab: 1825508 (addr 0x107577398 offset 123171736)
        Section __objc_classname: 67062 (addr 0x107734e7c offset 124997244)
        Section __objc_methname: 596059 (addr 0x107745472 offset 125064306)
        Section __objc_methtype: 389599 (addr 0x1077d6ccd offset 125660365)
        Section __cstring: 4263151 (addr 0x107835eb0 offset 126049968)
        Section __const: 4527489 (addr 0x107c46bc0 offset 130313152)
        Section __ustring: 4655330 (addr 0x108098142 offset 134840642)
        Section __unwind_info: 648680 (addr 0x108508a24 offset 139495972)
        Section __eh_frame: 359932 (addr 0x1085a7010 offset 140144656)
        total 140488162
    Segment __DATA: 31440896 (vmaddr 0x108600000 fileoff 140509184)
        Section __got: 18528 (addr 0x108600000 offset 140509184)
        Section __la_symbol_ptr: 64280 (addr 0x108604860 offset 140527712)
        Section __mod_init_func: 19480 (addr 0x108614378 offset 140591992)
        Section __const: 14553312 (addr 0x108619000 offset 140611584)
        Section __cfstring: 473664 (addr 0x1093fa0e0 offset 155164896)
        Section __objc_classlist: 22648 (addr 0x10946db20 offset 155638560)
        Section __objc_nlclslist: 536 (addr 0x109473398 offset 155661208)
        Section __objc_catlist: 280 (addr 0x1094735b0 offset 155661744)
        Section __objc_nlcatlist: 48 (addr 0x1094736c8 offset 155662024)
        Section __objc_protolist: 2872 (addr 0x1094736f8 offset 155662072)
        Section __objc_imageinfo: 8 (addr 0x109474230 offset 155664944)
        Section __objc_const: 2242360 (addr 0x109474238 offset 155664952)
        Section __objc_selrefs: 146928 (addr 0x109697970 offset 157907312)
        Section __objc_protorefs: 320 (addr 0x1096bb760 offset 158054240)
        Section __objc_classrefs: 20936 (addr 0x1096bb8a0 offset 158054560)
        Section __objc_superrefs: 13120 (addr 0x1096c0a68 offset 158075496)
        Section __objc_ivar: 46420 (addr 0x1096c3da8 offset 158088616)
        Section __objc_data: 282008 (addr 0x1096cf300 offset 158135040)
        Section __data: 1099512 (addr 0x1097140a0 offset 158417056)
        Section __thread_vars: 96 (addr 0x109820798 offset 159516568)
        Section __thread_bss: 69 (addr 0x1098207f8 zerofill)
        Section __bss: 10328904 (addr 0x109820840 zerofill)
        Section __common: 2087360 (addr 0x10a1fb000 zerofill)
        total 31423689
    Segment __LINKEDIT: 5301728 (vmaddr 0x10a3fc000 fileoff 159531008)
    total 4472219104

    不同段的说明

    段名 类别 说明
    __text __TEXT

    主程序代码

    otool -tv ./UAGame-IOS-Shipping // 查看可执行文件UAGame-IOS-Shipping代码段反编译内容

    __stubs __TEXT

    __stubs是一个表,每项是一小段会直接跳入laze binding的表对应项指针指向地址的代码(桩代码),存储外部函数

    otool ./UAGame-IOS-Shipping -s __TEXT __stubs

    __stub_helper __TEXT

    辅助函数,上述提到的laze binding的表中对应项的指针在没有找到真正的符号地址的时候,都指向这里

    otool -v ./UAGame-IOS-Shipping -s __TEXT __stub_helper

    __gcc_except_tab __TEXT gcc异常表
    __objc_classname __TEXT OC类名和用到的系统Protocol名称
    __objc_methname __TEXT OC方法名称
    __objc_methtype __TEXT OC方法类型
    __cstring __TEXT C语言字符串
    __const __TEXT const 关键字修饰的常量
    __ustring __TEXT unicode字符串
    __unwind_info __TEXT 用来存储处理异常情况信息
    __eh_frame __TEXT 调试符号信息
    __got __DATA

    用来存放外部全局变量/常量的最终地址值。在程序运行前(加载时)就会被绑定(non-lazy binding)

    对于程序段__text里的代码,对外部数据型符号的引用,会指向__got段
    可以把__got看作是一个表,每个条目是一个地址值。在符号绑定(binding)前,__got里所有条目的内容都是 0
    当镜像被加载时,dyld 会对__got每个条目所对应的符号进行重定位,将其真正的地址填入,作为条目的内容。

    otool ./UAGame-IOS-Shipping -s __DATA __got

    __la_symbol_ptr __DATA

    lazy绑定符号指针,表中的指针一开始都指向__stub_helper

    otool ./UAGame-IOS-Shipping -s __DATA __la_symbol_ptr

    __nl_symbol_ptr __DATA

    非lazy绑定符号指针,表中的数据为绑定后的地址(在加载时绑定好)

    注:__got是为__text代码段中的符号服务的,而__nl_symbol_ptr不是

    __mod_init_func __DATA 初始化函数,C++静态初始化、attribute等
    __mod_term_func __DATA 终止函数,main函数返回之后调用
    __const __DATA 未初始化过的常量
    __cfstring __DATA CFStringRefs字符串
    __objc_classlist __DATA OC类列表
    __objc_nlclslist __DATA

    实现了+(void)load方法的类

    注1:load方法是OC中一个特殊方法,在main函数之前,装载类信息时就会调用执行

    注2:load方法可以继承。调用子类的load方法之前,会先调用父类的load方法。

    __objc_catlist __DATA

    记录所有Category(分类)

    注:Category只能为已经存在的类添加方法,而不能添加成员变量

    __objc_nlcatlist __DATA

    实现了+(void)load方法的Category(分类)

    注1:Category(分类)也可以有load方法

    注2:优先调用类的load方法,之后再调用Category(分类)的load方法

    __objc_protolist __DATA OC原型列表
    __objc_imageinfo __DATA OC二进制信息
    __objc_const __DATA OC常量
    __objc_selrefs __DATA OC self引用
    __objc_protorefs __DATA OC原型引用
    __objc_classrefs __DATA OC原型引用(类方法)
    __objc_superrefs __DATA OC超类引用
    __objc_ivar __DATA OC成员变量
    __objc_data __DATA OC类信息,包括Meta_Class
    __data __DATA 初始化过的全局变量
    __thread_vars __DATA 与线程局部存储(TLS)有关
    __thread_data __DATA 同上
    __thread_bss __DATA 同上
    __bss __BSS  未初始化过或初始化为0的全局变量
    __common __BSS 未初始化过的符号声明
    Dynamic Loader Info  

    动态加载信息

    ① Rebase info:修复的是指向当前镜像内部的资源指针(mach-o每次加载到内存中不是固定的地址)

    ② Binding info:将外部符号进行绑定的过程

    ③ Weak Binding Info:针对弱符号进行绑定的过程, 在c语言中,函数、初始化的全局变量、static变量是强符号,未初始化的全局变量是弱符号。

        weakBinding这一步会把镜像中所有含有弱符号的映像合并成一个列表,再进行binding.。所以这一步放在最后,等加载完成后在做操作。

    ④ Lazy Binding Info:在加载动态库的时候不会立即binding, 当时当第一次调用这个方法的时候再实施binding。

    ⑤ Export Info:导出的函数

    Function Starts  

    入口函数

    Data in Code Entries  

    代码入口数据

    Symbol Table  

    所有符号表信息。包含调试符号、导出符号(MachOView中底色为黄色)和导入符号(MachOView中底色为绿色)

    注:debug版在该Table中会包含大量调试符号

    Dynamic Symbol Table   动态符号表。只包含导出符号和导入符号
    String Table   符号名表

    Category(分类)

    运行时(runtime)会将Category(分类)结构体中的instanceMethods(实例方法), protocols(协议),instanceProperties(实例属性  注:实例属性不是实例变量)添加到target class的实例方法列表,协议列表,属性列表中,

    会将Category(分类)结构体中的classMethods(类方法)添加到target class所对应的元类的实例方法列表中。

    经过这一番修改,Category(分类)中的方法,就变成了target class方法列表中的一部分。

    Lazy Binding

    首次访问外部的_say函数时:
    ① _say对应的__la_symbol_ptr条目内容指向到__stub_helper
    ② __stub_helper里的代码逻辑,通过各种辗转最终调用dyld_stub_binder函数(dyld_stub_binder函数定义于dyld_stub_binder.S,由 dyld 提供)
    ③ dyld_stub_binder函数通过调用 dyld 内部的函数找到_say符号的真实地址
    ④ dyld_stub_binder将地址写入__la_symbol_ptr条目
    ⑤ dyld_stub_binder跳转到_say符号的真实地址

    之后再次访问_say函数时,__stubs 里的 jmp 指令直接跳转符号的真实地址,因为该地址已经被写到__la_symbol_ptr条目中。

    不同配置的统计项的大小

    统计项 Debug Development Test Shipping
    可执行文件大小 879 MB 509 MB 396 MB 154 MB
    __text 0cf739a0 0a13058c 08df86d4 07274780
    __stubs 00018eac 00014040 00014004 00013db8
    __stub_helper 00004704 00004680 00004644 00004404
    __gcc_except_tab 001ad780 001cd528 001c9d4c 001b96a0
    __objc_classname 00010020 000101a6 00010020 00010020
    __objc_methname 000919bc 00091bf3 00091956 00091848
    __objc_methtype 0006127c 000624bc 000610e7 000610e7
    __cstring 0050d00d 004c5dff 00426edd 003b40ac
    __const 00652f31 0068d781 0067c0e1 0043a741
    __ustring 0065e7ea 0065b7d2 00536e38 0045e17c
    __unwind_info 000d49bc 000c51d0 000c2f44 000998ac
    __eh_frame 000c5bbc 000c5eb8 000c5eb8 00057dfc
    __got 00003cc8 00003c98 00003c58 00003460
    __la_symbol_ptr 000109c8 0000d580 0000d558 0000d3d0
    __nl_symbol_ptr
    __mod_init_func 00005220 00005188 00005100 00004c48
    __mod_term_func
    __const 00f29278 00ec7088 00e6cd40 00d9d1d0
    __cfstring 00074f00 00074fe0 00074e80 00074a00
    __objc_classlist 000056a0 00005700 000056a0 000056a0
    __objc_nlclslist 00000218 00000218 00000218 00000218
    __objc_catlist 00000118 00000118 00000118 00000118
    __objc_nlcatlist 00000030 00000030 00000030 00000030
    __objc_protolist 00000b30 00000b40 00000b30 00000b30
    __objc_imageinfo 00000008 00000008 00000008 00000008
    __objc_const 00223148 00224790 00223068 00222ec8
    __objc_selrefs 00024248 00024288 00024238 000241d8
    __objc_protorefs 00000140 00000148 00000140 00000140
    __objc_classrefs 00005048 000050a0 00005040 00005038
    __objc_superrefs 00003208 00003258 00003208 00003208
    __objc_ivar 0000b04c 0000b0fc 0000b030 0000b024
    __objc_data 00036240 00036600 00036240 00036240
    __data 001a1af8 0017cfd0 0015b6c8 0010fec8
    __thread_vars 00000138 00000138 00000138 00000060
    __thread_data 00000008 00000008 00000008 00000000
    __thread_bss 00000070 00000070 00000068 00000045
    __bss 0119fff0 0118b8c8 01134148 009ce578
    __common 00426b88 00424b88 003e4b88 002049c0

    参考

    iOS Category底层原理详细研究流程

    Mach-O 文件格式探索

    MachO文件格式

    Mach-O 与动态链接

    Mach-O 结构分析(一)

    Mach-O的动态链接相关知识

    灵犀iOS包体积优化

    如何解决IOS可执行文件TEXT段超标

    How to optimize today’s headline IOS installation package

    今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小

    [今日头条]iOS 包大小二进制优化,一行代码减少 60 MB 下载大小

  • 相关阅读:
    poj 1860 Currency Exchange(最短路径的应用)
    poj 2965 The Pilots Brothers' refrigerator
    zoj 1827 the game of 31 (有限制的博弈论)
    poj 3295 Tautology (构造法)
    poj 1753 Flip Game(枚举)
    poj 2109 (贪心)
    poj 1328(贪心)
    Qt 对单个控件美化
    Qt 4基础
    Bash Shell
  • 原文地址:https://www.cnblogs.com/kekec/p/15533060.html
Copyright © 2011-2022 走看看