如何手动解析CrashLog
2015-08-03 13:41
281 查看
http://www.cocoachina.com/ios/20150803/12806.html
解决崩溃问题是移动应用开发者最日常的工作之一。如果是开发过程中遇到的崩溃,可以根据重现步骤调试,但线上版本就无能为力了。好在目前已经有很多不错的第三方CrashLog搜集平台(如友盟、Crashlytics等)为我们做好了解析工作,甚至在Xcode7里苹果也跟进了解析线上版本崩溃日志的功能,为开发者减轻了不少负担。尽管通常已经不需要我们手工处理CrashLog,了解CrashLog的还原原理和方法还是有必要的。
一、.dSYM
.dSYM(debugging SYMbols)又称为调试符号表,是苹果为了方便调试和定位问题而使用的一种调试方案,本质上使用的是起源于贝尔实验室的DWARF(Debugging With Attributed Record Formats),其在.xcarchive目录中的层次结构为:
关于DWARF的具体内容以后有机会再说。我们能解析CrashLog全靠.dSYM文件,解析方式见后文。
二、确定符号表和崩溃日志的一致性
有了符号表文件,有了崩溃日志文件,在解析之前一定要确保二者的对应关系,否则就算按照下述步骤解析出内容也肯定是不准确的。二者的对应关系可以通过UUID来确定。
1、从崩溃日志中获取UUID
崩溃日志比较靠下的位置有个Binary Images模块,其第一行内容如下:
从中可以看到关于你应用的若干信息:
代码段的起终地址为:0xa2000 – 0x541fff
运行你应用的CPU指令集为:armv7
应用的UUID为:a5c8d3cfda65396689e4370bf3a0ac64(不区分大小写)
2、从符号表中获取UUID
执行以下命令从符号表中提取UUID:
或者:
执行结果为:
由此得到armv7指令集的UUID为:A5C8D3CF-DA65-3966-89E4-370BF3A0AC64(如果你的二进制文件支持多个指令集,这里会列出每个指令集对应符号表的UUID),通过和崩溃日志中的对比发现二者一致,才可进行进一步的解析操作。
三、计算崩溃符号表地址
以下面的崩溃堆栈为例:
1、 符号表堆栈地址计算方式
要想利用符号表解析出崩溃对应位置,需要计算出符号表中对应的崩溃堆栈地址。而从上述堆栈中第9行可以看到,应用崩溃发生在运行时地址0x000f0846,该进程的运行时起始地址是0xa2000,崩溃处距离进程起始地址的偏移量为十进制的321606(对应十六进制为0x4E846)。三者对应关系:
对应的公式为:
崩溃堆栈中的起始地址和崩溃地址均为运行时地址,根据虚拟内存偏移量不变原理,只要提供了符号表TEXT段的起始地址,再加上偏移量(这里为0x4E846)就能得到符号表中的堆栈地址,即:
2、获取符号表中的TEXT段起始地址
符号表中TEXT段的起始地址可以通过以下命令获得:
运行结果中的片段如下:
其中的vmaddr 0x00004000字段即为TEXT段的起始地址。
3、计算符号表地址
由公式:
可得:
即符号表中的崩溃地址为0x52846,接下来就可以根据这个地址解析出崩溃位置了。
四、崩溃信息还原
有了符号表的崩溃地址,有以下几种方式解析崩溃信息:
1、dwarfdump
命令如下:
需要注意的是:
这里的armv7是运行设备的CPU指令集,而不是二进制文件的指令集
比如armv7指令集的二进制文件运行在arm64指令集的设备上,这个地方应该写arm64。
—lookup后面跟的一定是经过准确计算的符号表中的崩溃地址
使用dwarfdump解析的结果较杂乱,因此使用grep命令抓取其中关键点展示出来
运行结果如下:
其中第一行是编译时文件目录,第二行包含了崩溃发生的文件名称以及文件中具体行号等信息,有了这些信息就能准确定位崩溃原因啦。
2、atos
atos是另一种更加简洁的崩溃日志解析方法,使用方式如下:
其执行结果如下:
相对dwarfdump命令的解析结果,更加简洁直观的指出了崩溃发生的位置。
3、无需符号表崩溃地址的解析方式
实际上,atos还提供了另外一种无需计算崩溃地址对应的符号表地址的方式,命令格式如下:
其中-l选项指定了二进制文件在运行时的起始地址0xa2000(获取方式见Binary Images相关内容),后面跟的是崩溃发生的运行时地址0x000f0846,解析结果和使用计算得到的符号表中崩溃地址一致:
五、参考文档
How to Match a Crash Report to a Build
CrashReporter
Understanding and Analyzing iOS Application Crash Reports
atos and dwarfdump won’t symbolicate my address
解决崩溃问题是移动应用开发者最日常的工作之一。如果是开发过程中遇到的崩溃,可以根据重现步骤调试,但线上版本就无能为力了。好在目前已经有很多不错的第三方CrashLog搜集平台(如友盟、Crashlytics等)为我们做好了解析工作,甚至在Xcode7里苹果也跟进了解析线上版本崩溃日志的功能,为开发者减轻了不少负担。尽管通常已经不需要我们手工处理CrashLog,了解CrashLog的还原原理和方法还是有必要的。
一、.dSYM
.dSYM(debugging SYMbols)又称为调试符号表,是苹果为了方便调试和定位问题而使用的一种调试方案,本质上使用的是起源于贝尔实验室的DWARF(Debugging With Attributed Record Formats),其在.xcarchive目录中的层次结构为:
二、确定符号表和崩溃日志的一致性
有了符号表文件,有了崩溃日志文件,在解析之前一定要确保二者的对应关系,否则就算按照下述步骤解析出内容也肯定是不准确的。二者的对应关系可以通过UUID来确定。
1、从崩溃日志中获取UUID
崩溃日志比较靠下的位置有个Binary Images模块,其第一行内容如下:
代码段的起终地址为:0xa2000 – 0x541fff
运行你应用的CPU指令集为:armv7
应用的UUID为:a5c8d3cfda65396689e4370bf3a0ac64(不区分大小写)
2、从符号表中获取UUID
执行以下命令从符号表中提取UUID:
三、计算崩溃符号表地址
以下面的崩溃堆栈为例:
要想利用符号表解析出崩溃对应位置,需要计算出符号表中对应的崩溃堆栈地址。而从上述堆栈中第9行可以看到,应用崩溃发生在运行时地址0x000f0846,该进程的运行时起始地址是0xa2000,崩溃处距离进程起始地址的偏移量为十进制的321606(对应十六进制为0x4E846)。三者对应关系:
符号表中TEXT段的起始地址可以通过以下命令获得:
3、计算符号表地址
由公式:
四、崩溃信息还原
有了符号表的崩溃地址,有以下几种方式解析崩溃信息:
1、dwarfdump
命令如下:
这里的armv7是运行设备的CPU指令集,而不是二进制文件的指令集
比如armv7指令集的二进制文件运行在arm64指令集的设备上,这个地方应该写arm64。
—lookup后面跟的一定是经过准确计算的符号表中的崩溃地址
使用dwarfdump解析的结果较杂乱,因此使用grep命令抓取其中关键点展示出来
运行结果如下:
2、atos
atos是另一种更加简洁的崩溃日志解析方法,使用方式如下:
3、无需符号表崩溃地址的解析方式
实际上,atos还提供了另外一种无需计算崩溃地址对应的符号表地址的方式,命令格式如下:
How to Match a Crash Report to a Build
CrashReporter
Understanding and Analyzing iOS Application Crash Reports
atos and dwarfdump won’t symbolicate my address
相关文章推荐
- [深入理解Android卷二 全文-第四章]深入理解PackageManagerService
- add_header X-Frame-Options "SAMEORIGIN";NGINX
- AudioManager的简单使用
- MD5加密
- 微信开发总结 四
- IIFE (Imdiately Invoked Function Expression 立即执行的函数表达式)。
- spring和mybatis整合进行事务管理
- Android开发问题集合
- leetcode 66: Plus One
- Bus System
- Scikit-Learn:开源的机器学习Python模块
- poj 3041 构图+最小点覆盖
- maven 在 mac中的配置
- Linux下快速安装Mysql及使用
- 网络路由设计基础
- git笔记
- C++读取mat文件 & VS2010 环境配置
- Linux C 堆与栈的区别
- 【Unity 教程】对象池
- HNU Knockout Racing