最近研究了一下符号表解析的方法,这里记录一下。
一.获取偏移地址
这里先看一个崩溃的日志,如下:
崩溃日志
崩溃日志
如图,图1第7行,是对应工程名的一行,可以看到一共有3个数字
0x000000010516c414 //运行时的内存地址
0x102dc8000 //运行时的起始地址
37372948(0x23A4414) //偏移地址
上面3个数字, 0x000000010516c414 = 0x102dc8000 + 37372948
这里,起始地址和内存地址都是运行是的,每次启动都会产生变化。
重要的是偏移地址37372948(0x23A4414),偏移地址是固定的。
二.确定符号表一致性
然后我们来说符号表文件,首页要确定符号表文件和崩溃日志是对应的,这里通过UUID来确定,崩溃日志的UUID就在图2的下面,符号表的UUID可以通过命令dwarfdump --uuid Your.app.dSYM
获取。
UUID
三.读取符号表
这里使用MachOView打开符号表文件,这里我们使用的arm64架构,所以也以此架构来说明。首先查看__TEXT
segment的虚拟地址
TEXT
可以看到__TEXT
的起始地址是0x0000000100000000
,上面我们获取到的偏移地址是37372948(0x23A4414)
,相加,获得在代码段的虚拟地址为0x1023A4414
。
0x0000000100000000 + 37372948(0x23A4414) = 0x00000001023A4414
查找符号表,确定0x1023A4414
所在位置
函数虚拟内存地址
查找得到0x1023A42BB < 0x1023A4414 < 1023A4F68
,所以可知,函数名为__ZL19CLSTerminateHandlerv,因为这个类因为是第三方的framework,不是源码依赖,所以这里显示的有些异常.
0x1023A4414
四、崩溃堆栈
last
Last Exception Backtrace
部分,最后的异常堆栈,一样可以像上面一样解析。上图可知,我们image的运行时内存地址是0x102dc8000 ~ 0x109d9bfff
,通过对比,异常堆栈中的内存地址0x10787dbdc(第6个), 0x108a160e8(第9个)
等等都在上述区间,这里使用0x108a160e8
来作为例子解说。
0x108a160e8 这个就是上面说的运行时的内存地址
0x102dc8000 ~ 0x109d9bfff 这个就是运行时的起始地址和结束地址,这里的起始地址和上面的是同一个,是因为上面我们看的也是同一个image。
所以这里可以算出偏移量: 0x108a160e8 - 0x102dc8000 = 0x5C4E0E8
使用偏移量+__TEXT虚拟地址: 0x0000000100000000 + 0x5C4E0E8 = 0x105C4E0E8
这里得到函数的虚拟地址为0x105C4E0E8
,同上面一样,查询可得
0x105C4E0E8