Crash的收集
- 使用Xcode从设备中获取Crash日志,新建工程CrashTest;
- 将你的iPhone手机连接到Mac,然后选择
Xcode->Windows->Device and Simulator,然后点击View Device Logs,你会看到手机上会有好多Log,其中Type为Crash的就是崩溃的Log,如下图所示:

Snip20210122_53.png
- 经过多方测试需要将iPhone从Mac上断开链接,当场发生的崩溃才立即会显示,否则不会立即显示;

Snip20210123_69.png
- 从真机设备中直接获取Crash日志;
- 1)打开
设置->隐私->分析->分析数据,在其中找到你想要的应用程序的日志,日志将使用以下格式命名:<应用名称> _ <崩溃时间> _ <设备名>; - 2)选择所需的日志,复制文本或点击右上角的分享按钮分享出去,并且把分享得到的.ips.synced或者复制文本而来的.txt文件的后缀名改为.crash,因为Xcode不接受没有.crash扩展名的崩溃日志;
- 1)打开

Snip20210123_68.png
Crash分析定位
在分析Crash之前我们首先来了解一下
.dSYM文件;dSYM 是保存十六进制函数地址映射信息的中转文件,我们调试的 symbols 都会包含在这个文件中,每次编译项目的时候都会生成一个新的 dSYM 文件,我们应该保存每个正式发布版本的 dSYM 文件,以备我们更好的定位问题,一般是在我们 release打包Archives 时保会存对应的版本文件,里面也有对应的.dSYM 和 .app 文件;dSYM文件路径为:
~/Library/Developer/Xcode/Archives;

Snip20210122_54.png

Snip20210122_56.png

Snip20210122_57.png
-
dSYM 文件在 debug 模式下默认是不生成的,我们需配置Build Settings -> Debug Information Format下,将 DWARF 修改为DWARF with dSYM File,再重新编译下就能生成 .dSYM文件了,直接去项目工程的Products 目录下找就行;

Snip20210121_40.png
方法一:使用symbolicatecrash工具进行crash分析,下面使用的是Debug模式下生成的相关文件进行实例分析,正式release环境会涉及到打包和开发者账号,有点麻烦;
- symbolicatecrash 是 Xcode 自带的 crash 日志分析工具,在终端中输入命令:
find /Applications/Xcode.app -name symbolicatecrash -type f,定位到它如下所示:

Snip20210121_44.png
可以看到返回了五个不同的路径,我使用的路径是:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash定位到路径中,内容如下所示:

Snip20210121_45.png
-
在桌面上新建一个crash_test文件夹,然后将上面截图中的symbolicatecrash文件,拷贝出来放在新建的crash_test文件夹中; - 在Release生产环境时,打开工程,配置好证书与描述文件,然后archive打包;
打包成功之后Xcode千万不能直接编译运行真机安装app(会造成crash文件与dSYM文件不匹配),app的安装需要从archive中导出的ipa,然后安装ipa文件到真机上,真机运行app,导致崩溃会生成.crash文件,在Debug环境时,设置好配置直接在真机上运行就可以了; - crash文件的导出 见上面的 使用Xcode从设备中获取Crash日志 或者直接从真机中导出隔空投送给Mac,
将导出的.crash文件也拷贝放到新建的crash_test文件夹中;

Snip20210122_59.png
- 在Release生产环境时,将archive包中的dSYM文件拷贝出来放在crash_test文件夹中,在Debug环境时,直接去项目工程的 Products 目录下找到dSYM文件拷贝出来放在crash_test文件夹中,
至此crash_test文件夹中有三个文件分别是:dSYM文件,symbolicatecrash文件和.crash文件`;

Snip20210122_60.png
- 在进行.crash文件符号化之前必须要检测
.crash文件和.dSYM文件是否匹配,只有当两者匹配了,才能正确的符号化,;
- UUID 是由一组 32 位数的十六进制数字所构成,每一个可执行程序都有一个 build UUID 唯一标识,由这个可执行程序生成的.crash文件,.dSYM文件和.app文件的UUID都是一致的,都是这个可执行程序的build UUID;
- 可执行程序的工程代码在不断的迭代,所以其UUID在不同版本时都会不同,那么对应生成的.crash文件,.dSYM文件和.app文件的UUID也都不同,为了正确的定位分析crash,必须要保证.crash文件,.dSYM文件和.app文件的UUID相同;
- 查询.crash文件的UUID, cd到.crash文件所在的文件夹,然后输入终端命令:
grep --after-context=2 "Binary Images:" *crash; - 查询.dSYM文件的UUID cd到.dSYM文件所在的文件夹,然后输入终端命令:
dwarfdump --uuid CrashTest.app.dSYM - 查询.app文件的UUID cd到.app文件所在的文件夹,然后输入终端命令:
dwarfdump --uuid CrashTest.app/CrashTest - .crash文件符号解析 cd到新建的crash_test文件夹下执行下面的命令:
./symbolicatecrash crash文件路径 dSYM文件路径 > YYCrashTest.crash - 可能报下面的错误:
Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 69.,解决方案如下: - 删除YYCrashTest.crash文件 执行下面的命令:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer - 然后再次执行上面的命令:
./symbolicatecrash crash文件路径 dSYM文件路径 > YYCrashTest.crash - 如果crash文件与dSYM文件不匹配即UUID不一致,会报以下错误:
No symbolic information found,表明两者不匹配; - 如果crash文件与dSYM文件匹配 即UUID一致,那么会生成一个新的YYCrashTest.crash文件,此文件是经过符号化的;

Snip20210122_63.png
- 拿原来的CrashTest-2021-01-22-103943.crash文件(从真机上导出的crash文件)与经过符号化的新生成的YYCrashTest.crash文件进行一个比对:

Snip20210122_66.png
方法二: 使用命令行工具 atos
- 同样使用atos也需要crash文件和dSYM,并且两者的UUID要一致;
- 打开crash文件 找到对应的内存地址 如下所示:

Snip20210123_71.png
终端 cd到dSYM所在文件 执行下面的命令:
xcrun atos -o CrashTest.app.dSYM/Contents/Resources/DWARF/CrashTest -arch arm64 -l 0x102110000(内存地址)回车后 再输入slide adress 最终看到的结果是:

Snip20210123_72.png
- 注意arm64是dSYM文件架构 可能是armv7要根据dSYM文件的实际架构填写,否则会报错如下:
atos cannot load symbols for the file CrashTest for architecture armv7
方法三: GitHub上有个工具,可以辅助我们解析 dSYMTools
- 界面如下所示:

Snip20210123_73.png
总结
- crash分析定位三种方法:
- symbolicatecrash工具;
- atos工具;
- dSYMTools工具;
- 这三种方法都需要
crash文件和dsym文件且两者需匹配即UUID一致,其中symbolicatecrash定位更加精准;