一、dSYM 文件生成
1、Xcode 自动生成,配置:
Xcode -> Build Settings -> Code Generation -> Generate Debug Symbols -> Yes
Xcode -> Build Settings -> Build Option -> Debug Information Format -> DWARF with dSYM File
2、手动生成:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil
/Users/oudushu/Library/Developer/Xcode/DerivedData/YourApp-cqvijavqbptjyhbwewgpdmzbmwzk/Build/Products/Debug-iphonesimulator/YourApp.app/YourApp -o YourApp.dSYM
二、如何找到对应的 dSYM 文件:
- 从发布的归档包里面找: Xcode -> Window -> Organizer -> 找到打包好的文件(Show in Finder)-> 选中文件(右键显示包内容)-> dSYMs文件夹下就是了
- 从iTunes Connect里面找
- mdfind工具:mdfind “com_apple_xcode_dsym_uuids == E30FC309-DF7B-3C9F-8AC5-7F0F6047D65F”
三、symbolicatecrash
1、查找
find /Applications/Xcode.app -name symbolicatecrash -type f
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
2、使用
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
./symbolicatecrash ./appName.crash ./appName.app.dSYM > customName.log
四、atos
1、使用
atos -o yourAppName.app.dSYM/Contents/Resources/DWARF/yourAppName -arch arm64/armv7 -l <load-address> <address>
或
atos -o yourAppName.app.dSYM/Contents/Resources/DWARF/yourAppName -arch arm64/armv7 <address> // 崩溃地址对应的符号表地址
二、实践
1、直接传入基地址与方法地址
atos -o liveshow.app.dSYM/Contents/Resources/DWARF/liveshow -arch arm64 -l 0x100124000 0x00000001027bd964
__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2 (in liveshow) (BLCrashGurad.m:0)
2、计算崩溃地址对应的符号表地址
1、从崩溃堆栈文件可知:
- 运行时堆栈地址(0x00000001027bd964)
- 运行时起始地址(0x100124000)
- 偏移量(40474980,转为十六进制:0x2699964)
2、符号表堆栈地址计算方式: 运行时堆栈地址 = 运行时起始地址 + 偏移量
3、根据虚拟内存偏移量不变原理 符号表堆栈地址 = 符号表起始地址 + 偏移量
知道偏移量后,只需知道符号表起始地址,即可计算出符号表堆栈地址。
可通过 otool
工具获得 __TEXT 段起始地址:
otool -l liveshow.app.dSYM/Contents/Resources/DWARF/liveshow
Load command 3
cmd LC_SEGMENT_64
cmdsize 1912
segname __TEXT
vmaddr 0x0000000100000000
vmsize 0x0000000005bf8000
fileoff 0
filesize 0
maxprot 0x00000005
initprot 0x00000005
nsects 23
flags 0x0
0x0000000102699964 = 0x0000000100000000 + 0x2699964
atos -o liveshow.app.dSYM/Contents/Resources/DWARF/liveshow -arch arm64 0x0000000102699964
__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2 (in liveshow) (BLCrashGurad.m:0)
五、dwarfdump
1、DWARF(Debugging With Attributed Record Formats)
.xcarchive –dSYMs |–Your.app.dSYM |–Contents |–Resources |–DWARF
2、查看 dSYM 文件的 UUID:
dwarfdump --uuid Your.app.dSYM
或
dwarfdump --uuid Your.app.dSYM/Contents/Resources/DWARF/Your
3、崩溃信息还原:
dwarfdump --arch armv7 Your.app.dSYM --lookup <address> // 符号表堆栈地址
dwarfdump --arch arm64 liveshow.app.dSYM --lookup 0x0000000102699964
liveshow.app.dSYM/Contents/Resources/DWARF/liveshow(arm64): file format Mach-O arm64
0x0218d124: Compile Unit: length = 0x00000a63, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x0218db8b)
0x0218d12f: DW_TAG_compile_unit
DW_AT_producer ("Apple clang version 12.0.0 (clang-1200.0.32.29)")
DW_AT_language (DW_LANG_ObjC)
DW_AT_name ("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods/BLCrashGuard/BLCrashGuard/Classes/BLCrashGurad.m")
DW_AT_LLVM_sysroot ("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk")
DW_AT_APPLE_sdk ("iPhoneOS14.4.sdk")
DW_AT_stmt_list (0x01351f66)
DW_AT_comp_dir ("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods")
DW_AT_APPLE_optimized (true)
DW_AT_APPLE_major_runtime_vers (0x02)
DW_AT_low_pc (0x00000001002c1c20)
DW_AT_high_pc (0x00000001026999f0)
0x0218da06: DW_TAG_subprogram
DW_AT_low_pc (0x0000000102699914)
DW_AT_high_pc (0x00000001026999f0)
DW_AT_frame_base (DW_OP_reg29 W29)
DW_AT_call_all_calls (true)
DW_AT_linkage_name ("__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2")
DW_AT_name ("__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2")
DW_AT_decl_file ("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods/BLCrashGuard/BLCrashGuard/Classes/BLCrashGurad.m")
DW_AT_decl_line (32)
DW_AT_prototyped (true)
DW_AT_APPLE_optimized (true)
Line info: file 'BLCrashGurad.m', line 0, column 91, start line 32
六、其它常用命令行工具
1、otool
otool命令全称object file displaying tool,是针对目标文件的展示工具,可以帮助我们发现应用中使用了哪些系统库,以及调用了哪些对象的方法和属性。 常用的几个子命令如下:
otool -L path // 查看可执行程序都链接了那些库
otool -ov path // 输出 Object-C 类结构以及定义的方法
2、lipo
lipo 命令的作用是 create or operate on universal files,即创建或处理通用文件的工具。 常用的几个子命令如下:
lipo -info XXX // 判断静态库所支持的平台 armv7 x86_64 arm64
lipo -remove armv7 origin_xxx.a -output op_xxx.a // 删除静态库包括的 armv7 平台
lipo -thin arm64 origin_xxx.a -output op_xxx.a // 拆分静态库,只保留 arm64 CPU 架构
lipo -create device_xxx.a simulator_xxx.a -output universal_xxx.a // 对真机或者模拟器分别打出 .a 文件合并
3、nm
nm 命令的作用是显示符号表,常用的几个子命令如下:
nm path //得到Mach-O中的程序符号表
nm -nm path //目标文件的所有符号
nm -u path //Display only undefined symbols.
4、strings
strings 命令,它可以帮助我们排查二进制文件中是否包含相关字符串,常用的命令为:
strings XXX | grep yourString
5、ar
ar -t xxx.a 可以知道静态库里的 .o 文件( .a 文件是 .o 文件的合集)