iOS dSYM文件结构剖析(下)

来源:互联网 发布:苗阜与姜昆的关系知乎 编辑:程序博客网 时间:2024/06/06 05:15

        在上次分享中,主要介绍了文件头数据的读取过程,实际上文件头的主要内容,标识文件结构,文件类型,各个Section在文件中的位置(偏移量)。正确读取了这些基本信息之后,就可以根据我们日常开发中的不同需求,去读取不同的内容了。了解了基本结构,以后如果有某些需求的话,就可以很快的进行数据的分析。今天就来说一说其中用的最多,也是最重要的一个功能,就是用来符号化,下面我们就来了解下是如何通过dSYM文件做符号化的。


符号表

在前面最后一节中了解了符号表数据在文件中的位置及其读取方法,符号表在dSYM文件中是连续的,以0结尾的字符串。在文件中它是怎么存在的。如图1所示: 



通过对符号表二进制的读取,最终我们可以整理出如图2一些数据。 



前面两列就是符号相对于加载地址的起始结束地址。为了便于展示,Demo中没有实现过多的函数,如果是比较大点的工程,这个列表就会变的很长。



调试行信息


通过前面对Section的读取,我们可以得到__debug_line在文件中的位置信息,如下图。这里主要存储了行号信息,是符号化必须的数据。这里的offset不是绝对的,是相对于Arch信息在文件中的偏移量来决定的。如图3所示。 


__debug_line在dSYM中是由如下的多块连续数据构成的,大小是由Section中的size字段决定的。如图4所示。



通过上面的二进制数据,可以整理出如下(图5)一些数据,这里是一些头部信息,可以得到本段的长度信息,文件名,文件所在的路径。特别要注意的是version,因为不同版本可能存在着差异。 



符号时,我们可能不需要知道文件所在的路径,但是我们需要知道符号所在的文件,所以在这里需要记下每个文件的序号,稍后解析行号的时候需要用到。在上篇分享中,读取数据都是有一定的结构的,解析起来相对容易,但是在读取调试信息时,可能没有固定的结构了,更多的就是文件存储,所以在读取时要遵循DWARF的标准去操作,不然很容易出现错误。



行号信息


现在就可以读取行号信息了,也就是图4中最后标记的那块数据。整理之后就像图6这样的一些数据,在这里可以得到符号的起始地址,文件序号,在文件中的行号。读取64-bit方法相同,只是有些数据的长度不同,比如地址长度是64位的。



通过对__debug_line数据读取整理后,我们最终可以得到如下图7的一组数据,有了图2和图7中的数据,最终我们可以得到符号所在文件的行号和起始结束地址。



到此,符号化的过程基本上就结束了,在得到程序的崩溃地址,就可以在我们整理出的数据中查到相应的行号信息。当然这里忽略了读取数据的一些细节,读取这些数据是相对繁琐的一个过程,而且容易出错,除非对DWARF格式十分的了解和熟悉。这里主要分享下解析的过程和原理,细节过多,不做赘述,当然符号化不止这一种方法,这是我实验的一种方法,还有一种方法可能更简单和直接。


对于iOS dSYM文件的分析,到这里基本就结束了,本来还想继续分享比如对__debug_pubnames, __debug_info, __debug_abbrev等等的调试信息的解析,但是想来想去在实际的开发工作中也用不到几次。所以在结束时,想到了我们用到的最多的符号化。至于其它的,以后有机会可以继续分享。其实,了解了符号的过程,其他的数据基本上也是大同小异,关键的难点不在于如何读取或者解析dSYM文件,而是在于DWARF这种调试格式文件本身,及其背后的一套逻辑。


以上是工作中需要处理的问题的一个过程,拿来分享。至于了解这些有何用处,那就是仁者见仁,智者见智。


最重要的还是过程。


0 1