前言
何谓符号化?简单来说就是把看不懂的十六机制地址转换为看得懂的函数名的这一过程,即为符号化。
当一个 app 发生 crash 时,操作系统会收集 app 发生崩溃时的各种诊断信息。其中对我们开发者最重要的一部分就是 thread backtraces,它会包含一系列的十六进制地址。开发者将其符号化之后,再根据相关的信息去定位崩溃的原因。
如何判断当前报告是否符号化
当你定位问题时,一份完整的符号化报告肯定是你最需要的,因为未符号化的报告都是十六进制地址,对我们来说是没有什么价值的。
完整符号化报告
一份完整的符号化报告,backtrace 的每一帧都会包含函数名,而不是十六进制的内存地址。每一帧则代表某一个具体线程上单个函数调用。下面是一个完整符号化报告的例子:
6 CrashDemo 0x104a69e0c -[ViewController touchesBegan:withEvent:] + 152
具体每一行代表什么含义可以参见这篇文章。
部分符号化报告
完整的符号化报告,每一帧都会包含函数名字。而部分符号化报告则是某些帧会包含函数名字,而有些帧则是包含十六进制地址。即使部分符号化报告提供了定位问题的线索,我们也应该将其完全符号化,来确保得到完整的线索。下面是一个部分符号化报告的例子:
5 CoreFoundation 0x19157c158 0x1022c0000 + 49064
6 CrashDemo 0x104a69e0c -[ViewController touchesBegan:withEvent:] + 152
未符号化报告
未符号化报告的每一帧都只包含十六进制地址,它对我们定位问题是没啥帮助的。下面是一个完整符号化报告的例子:
5 CoreFoundation 0x19157c158 0x1022c0000 + 49064
符号化的两种方式
用 Xcode 符号化
用 Xcode 符号化是官方推荐的一种方式,因为它会同时使用 Mac 上所有可用的 DSYM 文件来对报告进行符号化。
Tips:崩溃报告必须是 .crash
的文件后缀。如果文件没有后缀或者是别的后缀,比如 txt。必须将后缀改为 crash 再进行符号化。
- 选择 Xcode 的 Window - Devices and Simulators window
- 点击 Device Logs
- 将报告拖到空白处即可
如果执行完上面的操作,Xcode 并没有成功的将报告符号化,那你需要下面的步骤了:
- 如果是系统库没有被符号化,则你需要去找跟崩溃报告中系统库版本匹配的设备。
- 如果是自己的 app、app extension 或者 framework 未被符号化,你需要找到相应的 DSYM 文件。
用命令行符号化
当你没有完整的报告,只有某些未符号化的帧时,可以使用命令行工具来对每一帧进行符号化。
由 LLDB 提供的 atos
可以将十六进制的地址转为函数名和行号:
atos -arch <BinaryArchitecture> -o <PathToDSYMFile>/Contents/Resources/DWARF/<BinaryName> -l <LoadAddress> <AddressesToSymbolicate>
Tips:dSYM 文件是 macOS 包,其中包含带有调试符号的文件。当调用 atos 时,必须在包内提供此文件的路径,而不仅仅是外部 dSYM 包的路径。
下面是官网的示例图,标注了具体哪个参数对应哪个:
根据上图,atos 的命令如下:
atos -arch arm64 -o TouchCanvas.app.dSYM/Contents/Resources/DWARF/TouchCanvas -l 0x1022c0000 0x00000001022df754
输出如下:
ViewController.touchesEstimatedPropertiesUpdated(_:) (in TouchCanvas) + 304
总结
本文主要讲述了何为符号化、以及如何使用 Xcode 或 atos 进行报告符号化。希望本文会对大家进行线上崩溃问题定位时有帮助。