在 App 审核时,可能会出现类似下图这种被拒的情况:
原来出现了闪退,这对于 App 是个致命的问题,要马上修复。那么问题来了,我测试的时候没有崩溃的问题呀!我看不到 crash 的信息呀?我并不知道问题出现在哪里呀?
这时,我们就要用到崩溃日志了,这里面包含了我们需要的内容。当你拿到崩溃日志的时候,你看到的是这样的东西:
顿时一脸懵逼,感觉不会再爱了。
别急,只需要做一些简单的操作,把它符号化之后就变成人看的东西了。
本文将从以下几部分讲述崩溃日志符号化:
- 什么是崩溃日志
- 什么是符号化
- 如何判断符号化是否完成
- 如何获取崩溃日志
- 如何符号化
- 使用 symbolicatecrash 符号化
- 使用 Xcode 符号化
什么是崩溃日志
概念部分我们来看一下相关的官方文档。
When an application crashes, a crash report is created and stored on the device. Crash reports describe the conditions under which the application terminated, in most cases including a complete backtrace for each executing thread, and are typically very useful for debugging issues in the application. You should look at these crash reports to understand what crashes your application is having, and then try to fix them.
崩溃日志就是在 App 异常终止时,生成的记录运行环境、线程、栈回溯的用于调试的文件。
什么是符号化
Symbolication is the process of resolving backtrace addresses to source code method or function names, known as symbols. Without first symbolicating a crash report it is difficult to determine where the crash occurred.
符号化就是解决把栈回溯地址转化为为源码方法名或函数名的过程。
如何判断符号化是否完成
A crash report may be unsymbolicated, fully symbolicated, or partially symbolicated. Unsymbolicated crash reports will not contain the method or function names in the backtrace. Instead, you have hexadecimal addresses of executable code within the loaded binary images. In a fully symbolicated crash report, the hexadecimal addresses in every line of the backtrace are replaced with the corresponding symbol. In a partially symbolicated crash report, only some of the addresses in the backtrace have been replaced with their corresponding symbols.
Obviously, you should try to fully symbolicate any crash report you receive as it will provide the most insight about the crash. A partially symbolicated crash report may contain enough information to understand the crash, depending upon the type of crash and which parts of the backtraces were successfully symbolicated. An unsymbolicated crash report is rarely useful.
符号化分为三个级别:未符号化、半符号化和全符号化:
级别 | 特点 | 是否有用 |
---|---|---|
未符号化 | 全是十六进制地址 | 不是人给看的,基本没用 |
半符号化 | 部分十六进制地址、部分方法名函数名 | 部分是给人看的,有点用 |
全符号化 | 全是方法名函数名 | 全都是给人看的,特别有用 |
由此可见,全符号化才是最终的完成状态。
如何获取崩溃日志
- 审核时出现的问题,苹果官方会把崩溃日志作为回复的附件,直接点击下载即可。
- 从设备中获取(有时已经是完全符号化状态,可直接查看)
- 目标设备连接电脑 > 打开Xcode > Window > Devices (快捷键 shift + ⌘ + 2)
- 选择 View Devices Logs
- 在列表中选择文件,右键选导出
如何符号化
本文介绍两种方法,第一种相对第二种有些复杂,其实按步骤做也是很简单的
- 使用 symbolicatecrash 符号化
symbolicatecrash 是苹果官方提供的符号化工具,需要我们在终端输入命令执行,在此之前还有一些准备工作。
- 在桌面创建文件夹,把 symbolicatecrash、崩溃日志和 dSYM 文件放进去
首先,找到 symbolicatecrash,打开终端输入:
find /Applications/Xcode.app -name symbolicatecrash -type f
会输出 symbolicatecrash 的路径位置(可能不一样)
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash
拷贝 symbolicatecrash 文件到创建的文件夹中。
然后,查看崩溃日志文件的拓展名,如果是 .txt(苹果审核时返回的是.txt文件),修改为 .crash。
最后,找到崩溃日志对应的 dSYM 文件(dSYM 是保存十六进制函数地址映射信息的中转文件,符号化过程中的十六进制函数地址对应的方法名函数名就保存在这个文件中)。
dSYM 文件在打好的包中:
· 打开 Organizer 面板:Xcode > Window > Organizer
· 选择与崩溃日志版本对应的包,右键 Show In Finder
· 选择 xcarchive 文件,右键 显示包内容
· dSYM 文件就在 dSYMs 文件夹里
Xcode 默认打包时不创建 dSYM 文件,需要在 Build Settings 设置 Debug Information Format 为 DWARF with sSYM File(如下图),否则 dSYMs 文件夹是空的。
2.查看 dSYM 文件的 uuid,终端输入下面的命令
dwarfdump --uuid dSYM文件路径
得到如下输出:
UUID: CD78BB00-BE55-3FC2-89AC-580437E54D36 (armv7) + 很长的路径
UUID: AB0EC401-77B7-3FF6-BF99-567FA14A45FC (arm64) + 很长的路径
3.对比崩溃日志中的 uuid 与 输出的 uuid 是否一致
下面列出了崩溃日志中 Header 的部分信息:
{
"app_name": "XXXXXX",
"timestamp": "2017-06-03 02:15:01.50 +0800",
"app_version": "1.2.00",
"slice_uuid": "ab0ec401-77b7-3ff6-bf99-567fa14a45fc",
"adam_id": 1128617051,
"build_version": "1.0.1",
"share_with_app_devs": false,
"is_first_party": false,
"bug_type": "109",
"os_version": "iPhone OS 10.3.2 (14F89)",
"incident_id": "1DE9E3EF-D2DF-4A54-992A-1912BF8D285A",
"name": "XXXXXX"
}
Incident Identifier: 1DE9E3EF-D2DF-4A54-992A-1912BF8D285A
CrashReporter Key: 5abb1af3a567bd61ac640b7daf57c472c59d9547
Hardware Model: xxx
Version: 1.0.1 (1.2.00)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
这里我们需要关注两个字段 "Code Type" 和 "slice_uuid","Code Type"的类型为 ARM-64,所以从上一步输出的 UUID 信息中,找到 arm64 类型对应的 UUID 为 "AB0EC401-77B7-3FF6-BF99-567FA14A45FC",对比 Header 信息中的 "slice_uuid",如果不一致,说明生成崩溃日志的应用包与当前 dSYM 所在的包不同;如果一致,进行下一步。
4.执行 symbolicatecrash 命令
终端 cd 到第1步创建的文件夹,先定义 DEVELOPER_DIR:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
执行符号化:
./symbolicatecrash XXXX/XXXX/appName.crash XXXX/XXXX/appName.app.dSYM > customName.crash
命令执行完成后,在文件夹中会多出一个 customName.crash 文件,不出意外的话,这个就是完成符号化的崩溃日志。
PS:这个命令中 .crash 文件的路径一定要在 .dSYM 文件路径之前,否则会符号化失败;路径可以简化为 ./,生成的文件拓展名也可以为 log、txt等
./symbolicatecrash ./appName.crash ./appName.app.dSYM > customName.log
5.查资料的时候,有些文章上说用 symbolicatecrash 符号化还需要应用的 .app 文件,我没有把这个文件放到创建的文件夹中,符号化也成功了,如果大家在操作的时候出现了什么问题,可以先试试复制一份 .app 文件到文件夹中,再执行命令。
应用的 .app 文件,在打包后导出的 .ipa 文件里。把 .ipa 文件的拓展名改成 .zip,解压打开,在 Payload 文件夹中。
- 使用 Xcode 符号化
这种方式比较简单,具体操作如下:
首先,处理崩溃日志的拓展名如果不是 .crash 需要改成 .crash。
然后,设备连接电脑 > 打开Xcode > Window > Devices (快捷键 shift + ⌘ + 2),选择 View Devices Logs
最后,把崩溃日志拽到左侧的列表中,Xcode 就会自动符号化。
当然,这种方式也要满足一定条件这,如 Mac 中要有应用的二进制文件和 dSYM 文件。
To symbolicate a crash report, Xcode needs to be able to locate the following:
·The crashing application's binary and dSYM file.
·The binaries and dSYM files for all custom frameworks that the application links against. For frameworks that were built from source with the application, their dSYM files are copied into the archive alongside the application's dSYM file. For frameworks that were built by a third-party, you will need to ask the author for the dSYM file.
结果对比分析
完成符号化之后,我们来对比一下未符号化和全符号化的崩溃日志,还有 Xcode 控制台打印的关键信息(只截取部分信息)。
由此可见,正如前面所说,符号化完成后,崩溃日志中所有的十六进制地址都转化为了方法名函数名,而且与控制台打印的内容基本一致。
定位崩溃问题主要看 Last Exception Backtrace 部分,如红框所示,在 NSException 抛出异常之前,应用正在进行字符串截取,所以可能是字符串为空或 index 越界导致的。
关于崩溃日志符号化的操作就讲这么多。
第一次写东西,写得不是很好,如有问题欢迎指正。
**若有转载,请注明出处,谢谢~ **