iOS无dSYM符号表情况下的崩溃分析

一、dSYM符号表分析崩溃

在能够获取到dSYM符号表文件的情况下,分析崩溃详情请移步iOS crash 解析定位,shell脚本查找crash

或者使用可视化工具分析崩溃 CJCrashTools

CJCrashTools

二、无dSYM符号表文件崩溃分析

下面来讲一下本文的重点:无dSYM符号表文件下的崩溃分析。

要是很不幸缺失了dSYM文件,但如果能够获取到崩溃日志以及对应的.app文件的情况下,那么我们同样可以对崩溃详情进行分析。

获取crash log崩溃日志

  1. 将iOS设备连接到电脑上,打开 Xcode -> Window -> Devices and Simulators -> Devices,找到该台设备,点击View Device Logs,在 This Device的崩溃日志列表中中找到对应app的崩溃日志即可;也可以点击右键,Export Log将日志导出(后缀为 .crash 的 log 文件)。

  2. 如果你的应用已经上架App Store,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash log。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。

  3. 第三方crash收集系统,甚至还带了符号化crash日志的功能。比较常用的有CrashlyticsFlurry等。

获取.app文件

  1. 如果是Xcode debug模式下崩溃获取.app文件:打开Xcode,找到项目工程Products文件夹下的编译产物,右键Show in Finder,即可找到 CJTest.app (本文示例.app名为CJTest.app,后同)。

  2. 如果是导出ipa安装之后的崩溃:修改.ipa后缀名为.zip,解压之后进入Payload文件夹,同样可以找到 CJTest.app 文件。注意如果是从App Store渠道获取的ipa文件,那么必须先经过砸壳处理!

.app文件瘦身(非必要步骤)

首先判断崩溃日志是来自arm64还是其他机器,以及得到的.app是否集成多架构。

查看.app架构,终端执行:

1
lipo -info CJTest.app/CJTest

如果结果提示本身就只包含arm64,那么可以跳过本步骤了。

否则执行以下指令进行瘦身:

1
lipo -thin arm64 CJTest.app/CJTest -out CJTest_arm64

符号恢复工具restore-symbol

下载后修改权限

1
chmod a+x restore-symbol

恢复符号

1
2
3
4
./restore-symbol -o CJTest_symbol CJTest

# 如果是.app有经过瘦身,则执行
./restore-symbol -o CJTest_arm64_symbol CJTest_arm64

最终得到恢复了符号表的二时制文件 CJTest_symbol

另外如果运行restore-symbol指令的过程中系统提示"无法打开restore-symbol,因为无法验证开发者“,可通过以下步骤解决:打开系统偏好设置选项 — 点击打开安全性与隐私选项 — 点击上方的通用选项 — 点击选中下方的任何来源选项即可。

Bug位置定位

最后执行指令,定位到最终的崩溃代码。

1
atos -arch arm64 -o CJTest_arm64_symbol -l 0x1045e8000 0x0000000105b8b738 0x0000000105b8b724

atos指令说明:

1
# atos -arch ”CPU架构“ -o “二进制文件” -l “起始地址” “一系列内存地址。。。”

-l 后面跟的是模块的起始地址,然后后面可以罗列很多内存地址,执行命令后会依次解析出,所罗列的内存地址对应的所有函数。

对应的崩溃日志快照说明:
crashlog1

crashlog2

Binary Images表示的是app崩溃时程序加载的所有库的快照,找到CJTest所在行,开始的地址区间0x1045e8000 - 0x10658ffff代表的是程序崩溃时的内存区间,其中起始地址为0x1045e8000。其后是对应的app二进制文件名,架构类型arm64,再后面的尖括号里对应的是uuid说明。