iOS Crash 堆栈还原

1.什么是dSYM文件

dSYM 文件是Xcode编译后,我们会看到一个同名的 dSYM 文件,dSYM 是保存 16 进制函数地址映射信息的中转文件,存储应用程序的调试 symbols。每次编译项目或者打包的时候都会生成一个新的 dSYM 文件,当我们软件release模式打包或上线后,不会像我们在Xcode中那样直观的看到用崩溃的错误,所以对于每一个发布版本我们都很有必要保存对应的 Archives 文件。不管你集没集成类似Buyly的三方,要符号化分析crash日志还是得要用到对应的dSYM文件,如果没有生成dSYM文件,可以看一下TARGETS下Build Settings里面有没有设置,如下图,文章可能有点啰嗦,请耐心浏览。

2.什么时候会用到dSYM文件

1、APP提交审核,有闪退bug被拒,审核人员基本会上传crash文件给你,这时候就要自己符号化分析了。

2、你们编译给测试同事的包,如果你们关系好,大概率会重现一遍给你看,不然可能就是导出一个ips文件直接丢给你了,也可能还有一些不太好复现的crash。

3、自己有时候调试的时候可能会用到。

注:ips文件和crash文件不一样,Xcode13,iOS15以前设备ips文件改后缀成crash好像可以,但是之后 Apple 对符号化文件格式进行了JSON支持, 所以针对iOS15 以上产生的崩溃文件, 写入方式应该是做了调整, 所以在对 iOS 15 以上崩溃文件进行符号化时, ips改后缀会出现符号化失败, 报错 No crash report version in file 的问题,改为直接使用 CrashSymbolicator.py下面会讲到。

注:如果是发布Testflight版本,有些公司APP更新前会先提交Testflight版本公测一下,然后很多crash的日志可以通过Apple Store Connect里面对应的应用,Testflight下的反馈崩溃里面看到,可以直接Xcode打开,直接到Window->Organize->Crashes下直观看到崩溃错误


3.dSYM,ips,crash文件怎么拿到

1、dSYM

编译后Xcode13以前应该在项目的Products文件夹下,右键Show in Finder。

Xcode13后位于(/Users/用户名/Library/Developer/Xcode/DerivedData/对应的应用程序/Build/Products/Debug-iphoneos)。

打包的话位于(/Users/用户名/Library/Developer/Xcode/Archives)目录下,也可以在Xcode选择Window->Organize->Archives,Show in Finder。

2、crash

手机插上电脑Xcode选择Window->Devices and Simulators,找到对应的iphone,View Device Logs,右键Export Log。

3、ips

可能是测试同事可能其它同事可能用户,手机不能连接到电脑,可以在手机设置->隐私->分析与改进->分析数据,可以搜索对应的.ips.sycned文件然后查看导出修改成.ips的后缀就行,如果不是一眼能看到就直接搜项目名字。

4.具体怎么利用dSYM符号化分析

注:dSYM文件要和crash,ips等文件一一对应,否则符号化会失败,比如你1.0.1产生的crash,ips文件要和1.0.1编译的dSYM文件匹配,注意每次编译都会生成新的dSYM文件

1、怎么查看dSYM和ips,crash文件是否一一对应

笔者创建的项目叫Test,查看crash,ips直接双击打开查看,在下面例子图有标记,dSYM使用终端命令查看如下,Test.app.dSYM修改为对应的就行

例子如下,终端显示的是符号 - 拼接的,crash和ips文件都是连起来的。

2、利用symbolicatecrash符号化分析crash文件

注:创建文件夹和文件夹放在哪都能自己看着办只要用到对应文件路径的时候,路径能对应就可以了,以下是笔者自己创建的方式。

首先在桌面创建一个dsym文件夹,里面再创建一个crash文件夹,dYSM文件和.crash文件拖入进去,symbolicatecrash复制进去(如果不复制工具出来,可以把文件复制到工具文件夹下执行命令),Result.crash是符号化分析后的产物,Makefile是一个用AppleScript写的一个脚本,打开执行就能得到Result.crash(前提里面写的一些路径得一一对应),还可以保存成一个应用程序双击打开执行,具体更多好玩的得自己去了解一下。symbolicatecrash工具存放在该路径下:

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources

如果不一样可能是Xcode名字不一样?可以利用下面的命令去查找,如过你的Xcode就叫Xcode话,不然改成自己Xcode路径:

find /Applications/Xcode.app -name symbolicatecrash -type f

当三个文件都在同一个文件夹下后,我们可以通过命令来得到符号化分析后的crash文件,依次执行,命令如下:注:如果不执行第二条命令会有意想不到的结果

 1 cd Desktop/dsym/crash
 2 export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer" 
 3 ./symbolicatecrash Test.crash Test.app.dSYM > Result.crash

我们可以先来看看Test.crash日志符号化前后最后异常回溯长什么样子:

3、利用atos命令定位问题

其实除了symbolicatecrash工具,atos命令也能简单的分析一下,Test.app.dSYM/Contents/Resources/DWARF/Test 这里就存着具体符号

atos -o 项目名.app.dSYM/Contents/Resources/DWARF/项目名 -l 基地址 偏移后的地址
笔者使用的命令参考如下
atos -o Test.app.dSYM/Contents/Resources/DWARF/Test -l 0x1026b4000 0x1026B9904

得到的结果如上,没错就是最后异常回溯的第5行,有没有发现偏移后的地址和第6行的第一个地址是一致的,所以第1个地址是开始地址,第2个地址是基地址,第3个 + 22788就是偏移量 这是十进制的,计算如下 0x1026b4000 + 0x000005904(22788转16进制后的值)= 0x1026B9904 直接百度16进制加减法 或者计算器切换16进制,大佬可以除外

4、利用CrashSymbolicator.py符号化解析ips文件 (用此方法解析成功了 测试切换服务器的崩溃日志)

CrashSymbolicator.py脚本存放在该路径下:

/Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/

如果不一样可能是Xcode名字不一样?可以利用下面的命令去查找,如过你的Xcode就叫Xcode话,不然改成自己Xcode路径:

find /Applications/Xcode.app -name CrashSymbolicator -type f

但是这回不能像复制symbolicatecrash工具一样复制出来了,因为这个脚本import其它文件也在同一个目录下,我们可以终端命令进入到这个文件夹下把 dSYM 文件和 ips 文件放入到该文件夹下执行符号化解析命令。

下面先看两个文件的对比。

CrashSymbolicator.py 操作稍微和 symbolicatecrash 会有些不同,因为是用 python 写的脚本,所以要使用 python3 来进行调用,否则会报错。(肯定有一大波人默默的在终端输入python查看版本号发现还是2.7左右的版本,内心一顿XXX,其实python3早已经安装了,不信你们终端直接输入python3试试,如果没有那得自己安装了……

python3 CrashSymbolicator.py -d /xxx.app.dSYM -o /xxx.crash -p /xxx.ips

-d '符号表路径' -o '输出符号化路径' -p '苹果给的崩溃日志'

如果是在 CrashSymbolicator.py 文件夹下操作,dSYM 和 ips 文件需要复制到该脚本文件夹下,命令如下:

1 cd /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources
2 sudo python3 CrashSymbolicator.py -d Test.app.dSYM -o Result.ips -p Test.ips

5.利用AppleScript脚本快速进行符号化分析

上述在文件夹里面执行命令虽然可以完成,但是比较麻烦,笔者做了个脚本执行,下面就看看脚本里面的代码(其实就是封装了几条命令)

同样首先在之前桌面的dsym文件夹下创建一个 ips 文件夹,dYSM文件和 .ips 文件拖入进去,Makefile脚本准备好,打开执行,Result.ips文件就出来了,

Makefile.scpt代码如下: (具体语法这里就不做讲解了,用户名需要替换成自己的用户名,路径可以自行根据需要更改)

# 打开终端APP
tell application "Terminal"
 # 拼接导出ips结果命令 在此处替换对应的路径
 set pythonOrderStart to "python3 CrashSymbolicator.py"
 # 三个路径的前面的空格不要忽略了
 set dSYMPath to " -d /Users/用户名/Desktop/dsym/ips/Test.app.dSYM"
 set outfilePath to " -o /Users/用户名/Desktop/dsym/ips/Result.ips"
 set ipsPath to " -p /Users/用户名/Desktop/dsym/ips/Test.ips"
 set pythonOrderEnd to ";"
 # 第一条命令 进入CrashSymbolicator.py对应的文件夹下执行操作 因为CrashSymbolicator.py关联其它的库也在这个文件夹内
 set order1 to "cd /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources;"
 # 第二条命令 分析导出ips结果文件
 set order2 to pythonOrderStart & dSYMPath & outfilePath & ipsPath & pythonOrderEnd
 # 第三条命令 打开分析的结果文件
 set order3 to "open Result.ips"
 # 拼接多条命令
 set order to order1 & order2 & order3
 #多条命令执行用;分割
 do script order
end tell

链接:https://www.jianshu.com/p/88c915cd0be5

作者:千同学

%s 个评论

要回复文章请先登录注册