objdump&otool&nm查看Mach-O

优质
小牛编辑
190浏览
2023-12-01

分析Mach-O文件

简介: Mach-O

工具

  • objdump

    objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具

  • otool

    用来查看可执行文件的mach-o信息

  • nm

    查看符号表的工具


一、查询mach-o文件中指定的的main函数入口

  • 使用objdump

      ❯ objdump -p ${MACH_PATH} | ag 'LC_MAIN' -A 3
    

    输出结果:

          cmd LC_MAIN
      cmdsize 24
      entryoff 8384
      stacksize 0
    

    使用的插件:


二、只看 Mach header

  • objdump既可以查看Mach-O文件, 也可以查看LinuxELF文件

      objdump --macho -private-header  ${MACH_PATH}
    

    输出结果:

      Mach header
          magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
      MH_MAGIC_64  X86_64        ALL  0x00     EXECUTE    27       3160   NOUNDEFS DYLDLINK TWOLEVEL PIE
    
  • 使用otool -h也是同样的效果

三、查看Mach-O文件的机器指令(__TEXT)

  • 使用工具objdump

      ❯ objdump --macho -d ${MACH_PATH}
    

四、otool查看Mach-O文件

  • 展示的数据比较原始

      otool -l ${MACH_PATH}
    
      (__TEXT,__text) section
      -[ViewController viewDidLoad]:
      100001e70:    55    pushq    %rbp
      100001e71:    48 89 e5    movq    %rsp, %rbp
      100001e74:    48 83 ec 20    subq    $32, %rsp
      100001e78:    48 89 7d f8    movq    %rdi, -8(%rbp)
      100001e7c:    48 89 75 f0    movq    %rsi, -16(%rbp)
      100001e80:    48 8b 45 f8    movq    -8(%rbp), %rax
      100001e84:    48 89 45 e0    movq    %rax, -32(%rbp)
      100001e88:    48 8b 05 11 75 00 00    movq    29969(%rip), %rax ## Objc class ref: ViewController
      100001e8f:    48 89 45 e8    movq    %rax, -24(%rbp)
      100001e93:    48 8b 35 de 74 00 00    movq    29918(%rip), %rsi ## Objc selector ref: viewDidLoad
      100001e9a:    48 8d 7d e0    leaq    -32(%rbp), %rdi
      100001e9e:    e8 55 05 00 00    callq    0x1000023f8 ## Objc message: -[[%rdi super] viewDidLoad]
      100001ea3:    48 83 c4 20    addq    $32, %rsp
      100001ea7:    5d    popq    %rbp
      100001ea8:    c3    retq
      100001ea9:    90    nop
      100001eaa:    90    nop
      100001eab:    90    nop
      100001eac:    90    nop
      100001ead:    90    nop
      100001eae:    90    nop
      100001eaf:    90    nop
      ...
    

五、 查看符号表

  • 使用工具: objdump查看符号表

      objdump --macho -syms ${MACH_PATH}
    
      SYMBOL TABLE:
      0000000100001e70 l     F __TEXT,__text -[ViewController viewDidLoad]
      0000000100001eb0 l     F __TEXT,__text -[AppDelegate application:didFinishLaunchingWithOptions:]
      0000000100001f30 l     F __TEXT,__text -[AppDelegate application:configurationForConnectingSceneSession:options:]
      0000000100002050 l     F __TEXT,__text -[AppDelegate application:didDiscardSceneSessions:]
      0000000100002150 l     F __TEXT,__text -[SceneDelegate scene:willConnectToSession:options:]
      0000000100002200 l     F __TEXT,__text -[SceneDelegate sceneDidDisconnect:]
      0000000100002240 l     F __TEXT,__text -[SceneDelegate sceneDidBecomeActive:]
      0000000100002280 l     F __TEXT,__text -[SceneDelegate sceneWillResignActive:]
      00000001000022c0 l     F __TEXT,__text -[SceneDelegate sceneWillEnterForeground:]
      0000000100002300 l     F __TEXT,__text -[SceneDelegate sceneDidEnterBackground:]
      0000000100002340 l     F __TEXT,__text -[SceneDelegate window]
      0000000100002360 l     F __TEXT,__text -[SceneDelegate setWindow:]
      00000001000023a0 l     F __TEXT,__text -[SceneDelegate .cxx_destruct]
      0000000100004050 lw    O __DATA_CONST,__objc_protolist __OBJC_LABEL_PROTOCOL_$_NSObject
      0000000100004058 lw    O __DATA_CONST,__objc_protolist __OBJC_LABEL_PROTOCOL_$_UIApplicationDelegate
      0000000100004060 lw    O __DATA_CONST,__objc_protolist __OBJC_LABEL_PROTOCOL_$_UISceneDelegate
      0000000100004068 lw    O __DATA_CONST,__objc_protolist __OBJC_LABEL_PROTOCOL_$_UIWindowSceneDelegate
      0000000100008050 l     O __DATA,__objc_const __OBJC_METACLASS_RO_$_ViewController
      0000000100008098 l     O __DATA,__objc_const __OBJC_$_INSTANCE_METHODS_ViewController
      00000001000080b8 l     O __DATA,__objc_const __OBJC_CLASS_RO_$_ViewController
      0000000100008100 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_INSTANCE_METHODS_NSObject
      00000001000082d0 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_NSObject
      00000001000082f0 l     O __DATA,__objc_const __OBJC_$_PROP_LIST_NSObject
      0000000100008338 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_METHOD_TYPES_NSObject
      00000001000083d8 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_REFS_UIApplicationDelegate
      00000001000083f0 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UIApplicationDelegate
      0000000100008908 l     O __DATA,__objc_const __OBJC_$_PROP_LIST_UIApplicationDelegate
      0000000100008920 l     O __DATA,__objc_const __OBJC_$_PROTOCOL_METHOD_TYPES_UIApplicationDelegate
      0000000100008ad0 l     O __DATA,__objc_const __OBJC_CLASS_PROTOCOLS_$_AppDelegate
      0000000100008ae8 l     O __DATA,__objc_const __OBJC_METACLASS_RO_$_AppDelegate
      ...
    

    g: 全局符号 全局变量
    l: 本地符号 static修饰的变量

    __attribute__((visibility("hidden"))) 将全局符号隐藏掉或者使用static修饰变量编程本地符号

    弱定义 -> 解决重复符号, 提前声明为弱定义, 在查找的时候找到一个就不会再去查找了
    弱引用 -> 链接时查找符号, 如果不存在, 不会crash

    例如:

      int hidden_y __attribute__((visibility("hidden"))) = 99;
    

六、查看导出符号(比如全局变量)

  • 全局符号 --> 导出符号 (strip 动态库时 不是全局符号的符号)

    OC默认都是全局符号/导出符号, 想要动态库的体积尽可能小, 尽量把不想暴露的符号strip

    OC方法不暴露方法也是导出符号

    • 符号的可剥离性

      1. App (导出符号一般不需要提供给外部使用, 导入符号不能脱(间接符号表))-> 本地 + 全局 都可以脱掉 = 只留下间接符号表中的符号
      2. 静态库 (.o 合集 + 重定位符号表) -> 重定位符号表中的符号在链接时需要使用, 只有调试符号可以脱掉 = .o中的所有符号 + 可定位的符号 (可能是全局、可能是本地也可能是导出)
      3. 动态库 -> 只要不是全局符号都可以脱掉 = app使用动态库时都放在间接符号表中
    • 从符号的角度考虑, 使用静态库体积会小一些

      • 通过Strip剥离符号时, 只要不是间接符号表中的符号都可以剥离, 而静态库在链接到App中时可能会是全局、本地、导出符号, 而动态库都存在间接符号表中
    • SDK提供商角度来讲, 动态库更具有优势, 符号信息会全一些

      将导出符号变成不导出

      -Xlinker -unexported_symbol -Xlinker __OBJC_METACLASS_RO_$_ViewController
      
      objdump --macho --exports-trie ${MACH_PATH}
      
      ❯ objdump --macho --exports-trie ${MACH_PATH}                                ─╯
      /Users/shenyj/Desktop/macho/MultiEnvByXCConfigWOConflict:
      Exports trie:
      0x100000000  __mh_execute_header
      0x1000020C0  _main
      0x1000093B0  _OBJC_CLASS_$_ViewController
      0x100009428  _OBJC_CLASS_$_AppDelegate
      0x100009478  _OBJC_CLASS_$_SceneDelegate
      0x1000093D8  _OBJC_METACLASS_$_ViewController
      0x100009400  _OBJC_METACLASS_$_AppDelegate
      0x100009450  _OBJC_METACLASS_$_SceneDelegate
      

七、查看间接符号表

  • 间接符号表 --> 动态库符号 (不能动)

      objdump --macho --indirect-symbols ${MACH_PATH}
    
      ❯ objdump --macho --indirect-symbols ${MACH_PATH}                            ─╯
      /Users/shenyj/Desktop/macho/MultiEnvByXCConfigWOConflict:
      Indirect symbols for (__TEXT,__stubs) 10 entries
      address            index name
      0x00000001000023d4   184 _NSStringFromClass
      0x00000001000023da   191 _UIApplicationMain
      0x00000001000023e0   194 _objc_alloc
      0x00000001000023e6   195 _objc_autoreleasePoolPop
      0x00000001000023ec   196 _objc_autoreleasePoolPush
      0x00000001000023f2   197 _objc_autoreleaseReturnValue
      0x00000001000023f8   199 _objc_msgSendSuper2
      0x00000001000023fe   200 _objc_opt_class
      0x0000000100002404   202 _objc_retainAutoreleasedReturnValue
      0x000000010000240a   203 _objc_storeStrong
      Indirect symbols for (__DATA_CONST,__got) 3 entries
      address            index name
      0x0000000100004000   198 _objc_msgSend
      0x0000000100004008   201 _objc_release
      0x0000000100004010   204 dyld_stub_binder
      Indirect symbols for (__DATA,__la_symbol_ptr) 10 entries
      address            index name
      0x0000000100008000   184 _NSStringFromClass
      0x0000000100008008   191 _UIApplicationMain
      0x0000000100008010   194 _objc_alloc
      0x0000000100008018   195 _objc_autoreleasePoolPop
      0x0000000100008020   196 _objc_autoreleasePoolPush
      0x0000000100008028   197 _objc_autoreleaseReturnValue
      0x0000000100008030   199 _objc_msgSendSuper2
      0x0000000100008038   200 _objc_opt_class
      0x0000000100008040   202 _objc_retainAutoreleasedReturnValue
      0x0000000100008048   203 _objc_storeStrong
    

八、nm 查看符号信息

  • 使用nm查询符号表信息, 利用-m参数输出格式会更友好一些

      nm -m ${MACH_PATH}