作者:qk墨砚轩 | 来源:互联网 | 2023-08-24 14:24
1.为什么崩溃日志需要解析如图所示是崩溃日志线程回溯信息,其中的调用堆栈都是二进制地址,而不是可读的函数名称因此需要对崩溃日志进行解析,解析成可以理解的函数调用堆栈。
1. 为什么崩溃日志需要解析
如图所示是崩溃日志线程回溯信息,其中的调用堆栈都是二进制地址,而不是可读的函数名称因此需要对崩溃日志进行解析,解析成可以理解的函数调用堆栈。
2.生成dSYM
符号文件
crashlog
解析需要调试符号表文件 dSYM(debugging symbols)
, dSYM
文件实际上是从Mach-O
文件抽取调试信息得到的文件目录。在编译工程时, debug
模式会默认选中生成dSYM
文件, 该配置可在 Build Setting|Build Option
中更改。 dSYM
文件生成比较耗时,如果不需要进行 crashlog
解析,可以选择不生成。
2.1 Debug
下可以在DeriveData
的目录下获取到dSYM文件
2.2 打包的时候可以在生成的.achive
目录下找到对应的dSYM
文件
2 解析方法
2.1 Xcode 解析
将crashlog
、 dSYM
文件和可执行文件放在同一目录下,然后将 crashlog
拖拽至 Devicelog
中,右键 Re-symbolicate Log
就能解析。
2.2 使用 symbolicatecrash 命令行解析
3.解析原理
dSYM 文件介绍
其中真正保存保存数据的是 DWARF 文件, DWARF(Debuging With Arbitrary Format)是ELF 和 Mach-O 等文件格式中用来存储和处理调试信息的标准格式。 DWARF 中的数据是高度 压 缩 的 , 可以通过dwarfdump
命令提取可读信息,比如提取关键的调试信息.debug_info、.debug_line。
注释: ELF
、Mach-O
用于存储二进制文件、可执行文件、目标代码和共享库的格式文件。
解析流程
- 计算崩溃地址对应符号表中的地址
以某 crashlog 文件为例,如下图所示。是一个Exception
类型的异常,从下至上依次为该线程的调用堆栈,右边红色框第一列为运行时的堆栈地址,第二列为进程运行时的起始地址(testxcConfig 所有行起始地址都相同),第三列为运行时的偏移地址。
运行时堆栈地址=运行时起始地址+偏移地址,以第 4 行为例。0x1022cd990=0x1022c8000 + 0x5990(22928)
,以上地址均为 app 发生崩溃时的运行地址,根据虚拟内存偏移地址不变的原理,只要知道符号表 TEXT 段的起始地址,加上偏移量(0x5990)就能得到崩溃地址对应符号表中的地址, 符号表 TEXT 段的起始地址可通过以下命令获得。
那么崩溃地址(0x1022cd990
)对应符号表中的地址为:0x100005990 =0x0000000100000000+0x5990
- 地址重映射
获取符号表地址后,在 debug-info
章节中查找包含该地址的 DIE(Debug Information Entry)
单元就能获知该符号地址对应的函数名称(name)、 函数所在的文件路径(decl file)和函数所在行数(decl line),如下图所示。
上述步骤解析出了函数相关信息, 下面进一步获取该地址对应的准确行数, 这需要借助debug_line
章节, debug_line
章节以文件为单位,准确记录了文件中的每一行对应的符号表地址, 0x100005990
对应 AppDelegate.m
的第 20
行。
- 手动解析 crashlog
当有完整的 crashlog
文件和对应的 dSYM
文件时,以上过程可以由 Xcode
自动完成。但对于用户反馈的 crash
, 需要用户手动复制本地的crashlog
文件,而通常crashlog 文
本较长,完整复制其实比较麻烦,那么此时可以只复制崩溃线程的 crash
信息,并通过手动解析。手动解析 crash
可以使用 dwarfdump、 atos
工具, 命令如下。
4.常见问题
-
如何找到crashlog
对应的 dSYM
文件?
打开终端,使用以下命令获取 dSYM
文件对应的 uuid
, 并与crashlog
文件Binary Image
后面的字符对比,如果字符完全相同,就说明 dSYM
文件与crashlog
对应。
另外可以使用mdfind命令去寻找指定uuid的dSYM
文件,如下,uuid需大写并转化成格式,如下图
mdfind "com_apple_xcode_dsym_uuids == D5644244-F2C4-3C96-BD63-EF0F4DA518FA"
-
如何手动生成 dSYM
文件?
如果在编译之前忘记在 buildsetting
中选中生成 dSYM
文件,然而 app 又发生了崩溃,那么可以通过 app 的可执行文件再手动生成 dSYM
文件。
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/ranjingfu/Desktop/testxcConfig/testxcConfig.app/testxcConfig -o out.dSYM
值得注意的是,只有可执行文件为 debug
模式产物时,才能使用上述方式手动抽取调试符号表文件(dSYM)
, release
模式无法抽取。 因为debug
产物会保存调试信息,而release
产物不会, dSYM
文件就是从调试信息中抽取出来的。
解析后的崩溃日志实例