接下来再说说dwarfdump、atos等解析工具是如何从符号表文件中获取到崩溃位置信息的。一切还得从.dSYM符号表文件开始提及。算法
1、.dSYM文件的生成app
符号表文件.dSYM其实是从Mach-O文件中抽取调试信息而获得的文件目录,实际用于保存调试信息的问价是DWARF,其出身能够从苹果员工的文章《Apple’s “Lazy” DWARF Scheme》了解一二。iphone
一、Xcode自动生成工具
Xcode会在编译工程或者归档时自动为咱们生成.dSYM文件,固然咱们也能够经过更改Xcode的若干项Build Settings来阻止它那么干。网站
二、手动生成ui
另外一种方式是经过命令行从Mach-O文件中手工提取,好比:spa
1prototype |
|
生成的位置在你命令行cd进入的位置该方式经过Xcode提供的工具dsymutil,从项目编译结果.app目录下的Mach-O文件中提取出调试符号表文件。实际上Xcode也是经过这种方式来生成符号表文件。debug
2、DWARF简介
DWARF(DebuggingWith Arbitrary Record Formats),是ELF和Mach-O等文件格式中用来存储和处理调试信息的标准格式,.dSYM中真正保存符号表数据的是DWARF文件。DWARF中不一样的数据都保存在相应的section(节)中,ELF文件里全部的section名称都以".debug_"开头,以下表所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Mach-O中关于section的命名和ELF稍有区别,把名称前的.换成了_,例如.debug_info变成了_debug_info。
3、section信息提取
保存在DAWARF中的信息是高度压缩的,能够经过dwarfdump命令从中提取出可读信息。前文所述的那些section中,定位CrashLog只须要用到.debug_info和.debug_line。因为解析出来的数据量较大,为了方便查看,就将其保存在文本中。两个section的数据提取方式以下:
.debug_info
1 |
|
.debug_line
1 |
|
命令中的-e能够增长解析结果的可读性;其它section的提取方式相似,详情请参考dwarfdump命令帮助信息。
4、解析崩溃地址
一、计算崩溃地址对应符号表中的地址
在上篇文章中,介绍了如何根据崩溃地址计算获得对应符号表中的地址,并获得了最终数值:0x52846,接下来咱们就经过这个值来介绍dwarfdump、atos等工具是如何解析崩溃日志的。
二、解析过程
.debug_info
.debug_info中最基本的描述单元为DIE(Debug Information Entry),详情请参考DWARF官方网站,首先咱们要根据符号表崩溃地址0x52846从.debug_info中取出包含这个地址的DIE单元。为了简单起见,直接贴出了从info-e.txt中取出的对应DIE,其部份内容以下:
1 2 3 4 5 6 7 8 9 10 |
|
能够看出,该DIE包含是方法-[OBDFirstConnectViewController showOilPricePickerView]的内容,其地址范围是0x000502e0–0x00053730,咱们的目标地址0x52846正是在这个范围内,因此能够断定崩溃发生在该方法的某一行中。
须要指出的是,上面这段DIE是我为了介绍方便直接贴出来的,实际应用的时候须要经过搜索算法找出包含目标符号表崩溃地址(这里是0x52846)的DIE。
从上述DIE中咱们能够获取到这些信息:
1 2 3 |
|
. debug_line
截止目前,咱们能够获取到发生了崩溃的方法的相关信息,但要想肯定崩溃发生的具体行号,还须要.debug_line的帮助。
.debug_line以一个方法为基本块,急了该方法中每一行对应的符号表地址。经过.debug_info得知崩溃发生的方法地址范围是0x000502e0–0x00053730,经过起始地址0x000502e0在解析. debug_line获得的line-e.txt中直接搜索便可获得崩溃所在方法的. debug_line数据,其中部份内容以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
. debug_line段的第一行内容标识了该方法的起始符号表地址,行号及方法所在文件路径,经过以前获得的崩溃地址0x52846便可得知崩溃发生在882行。
至此咱们已经根据崩溃地址解析出了崩溃发生位置的详细信息:
1 2 3 4 |
|