iOS崩溃日志解析&原理

1. 为何崩溃日志须要解析

如图所示是崩溃日志线程回溯信息,其中的调用堆栈都是二进制地址,而不是可读的函数名称所以须要对崩溃日志进行解析,解析成能够理解的函数调用堆栈。 xcode

2.生成dSYM符号文件

crashlog 解析须要调试符号表文件 dSYM(debugging symbols)dSYM 文件其实是从Mach-O 文件抽取调试信息获得的文件目录。在编译工程时, debug 模式会默认选中生成dSYM文件, 该配置可在 Build Setting|Build Option 中更改。 dSYM文件生成比较耗时,若是不须要进行 crashlog 解析,能够选择不生成。 markdown

2.1 Debug下能够在DeriveData的目录下获取到dSYM文件

2.2 打包的时候能够在生成的.achive目录下找到对应的dSYM文件

2 解析方法

2.1 Xcode 解析

crashlogdSYM 文件和可执行文件放在同一目录下,而后将 crashlog 拖拽至 Devicelog中,右键 Re-symbolicate Log 就能解析。 app

2.2 使用 symbolicatecrash 命令行解析

  • 1.首先找到symbolicatecrash的路径

一般symbolicatecrash的路径为/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash函数

  • 2.命令行解析

首先将崩溃日志,dSYM以及symbolicatecrash复制出来放到同一个文件夹,而后cd到当前文件夹 ,运行以下命令解析./symbolicatecrash temp.crash testxcConfig.app.dSYM > result.log 工具

  • 3.首次运行须要先运行命令export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"

3.解析原理

dSYM 文件介绍

其中真正保存保存数据的是 DWARF 文件, DWARF(Debuging With Arbitrary Format)是ELF 和 Mach-O 等文件格式中用来存储和处理调试信息的标准格式。 DWARF 中的数据是高度 压 缩 的 , 能够经过dwarfdump命令提取可读信息,好比提取关键的调试信息.debug_info、.debug_line。 注释: ELFMach-O用于存储二进制文件、可执行文件、目标代码和共享库的格式文件。 ui

解析流程

  1. 计算崩溃地址对应符号表中的地址

以某 crashlog 文件为例,以下图所示。是一个Exception类型的异常,从下至上依次为该线程的调用堆栈,右边红色框第一列为运行时的堆栈地址,第二列为进程运行时的起始地址(testxcConfig 全部行起始地址都相同),第三列为运行时的偏移地址。 运行时堆栈地址=运行时起始地址+偏移地址,以第 4 行为例。0x1022cd990=0x1022c8000 + 0x5990(22928),以上地址均为 app 发生崩溃时的运行地址,根据虚拟内存偏移地址不变的原理,只要知道符号表 TEXT 段的起始地址,加上偏移量(0x5990)就能获得崩溃地址对应符号表中的地址, 符号表 TEXT 段的起始地址可经过如下命令得到。 那么崩溃地址(0x1022cd990)对应符号表中的地址为:0x100005990 =0x0000000100000000+0x5990 2) 地址重映射 获取符号表地址后,在 debug-info 章节中查找包含该地址的 DIE(Debug Information Entry)单元就能获知该符号地址对应的函数名称(name)、 函数所在的文件路径(decl file)和函数所在行数(decl line),以下图所示。 上述步骤解析出了函数相关信息, 下面进一步获取该地址对应的准确行数, 这须要借助debug_line章节, debug_line 章节以文件为单位,准确记录了文件中的每一行对应的符号表地址, 0x100005990 对应 AppDelegate.m 的第 20 行。 3) 手动解析 crashlog 当有完整的 crashlog 文件和对应的 dSYM 文件时,以上过程能够由 Xcode 自动完成。但对于用户反馈的 crash, 须要用户手动复制本地的 crashlog 文件,而一般 crashlog 文本较长,完整复制其实比较麻烦,那么此时能够只复制崩溃线程的 crash 信息,并经过手动解析。手动解析 crash 可使用 dwarfdump、 atos 工具, 命令以下。spa

  • 方法一

  • 方法二

  • 方法三

方法2、三都使用了atos解析,区别是方法三不须要获取符号表地址, 其后倒数第一个地址为运行时堆栈地址,倒数第二个地址为进程起始地址。 手动解析另外一个应用场景是,若开发人员为了跟进某一偶现问题在日志中记录的是运行时的二进制地址,那么能够经过对应的 dSYM 文件手动解析出调用函数明文。命令行

4.常见问题

  1. 如何找到crashlog 对应的 dSYM 文件?

打开终端,使用如下命令获取 dSYM 文件对应的 uuid, 并与crashlog文件Binary Image后面的字符对比,若是字符彻底相同,就说明 dSYM文件与crashlog对应。 另外可使用mdfind命令去寻找指定uuid的dSYM文件,以下,uuid需大写并转化成格式,以下图 mdfind "com_apple_xcode_dsym_uuids == D5644244-F2C4-3C96-BD63-EF0F4DA518FA" 线程

  1. 如何手动生成 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文件就是从调试信息中抽取出来的。debug

解析后的崩溃日志实例

相关文章
相关标签/搜索