objdump&otool&nm查看Mach-O
优质
小牛编辑
190浏览
2023-12-01
分析Mach-O
文件
简介: Mach-O
工具
一、查询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
文件, 也可以查看Linux
的ELF
文件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
方法不暴露方法也是导出符号符号的可剥离性
- App (导出符号一般不需要提供给外部使用, 导入符号不能脱(间接符号表))-> 本地 + 全局 都可以脱掉 = 只留下间接符号表中的符号
- 静态库 (.o 合集 + 重定位符号表) -> 重定位符号表中的符号在链接时需要使用, 只有调试符号可以脱掉 = .o中的所有符号 + 可定位的符号 (可能是全局、可能是本地也可能是导出)
- 动态库 -> 只要不是全局符号都可以脱掉 = 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}