• 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 下载大小

  • 相关阅读:
    中科院大牛博士是如何进行文献检索和阅读(好习惯受益终生)(转载)
    大家平常都喜欢看哪些人的博客,共享…… ZZ (水木)
    heart ultrasound from american society of echocardiography
    用TWaver实现组合的Chart
    Hello TWaver Android
    关注细节-TWaver Android
    TWaver Java内存占用测试
    TWaver Android 概述
    机器学习中的相似性度量
    最大熵模型(一)
  • 原文地址:https://www.cnblogs.com/kekec/p/15533060.html
Copyright © 2020-2023  润新知