趣探 Mach-O:符号解析

502 查看

这是 Mach-O 系列的第二篇,这篇文章我理解起来感觉不是特别深入,如有问题还望指出,目前也在做更多 Mach-O 的总结,如有新的理解,我也会及时更新文章

符号解析中会遇到很多名词和函数,首先介绍一下这些知识点,然后符号解析会参照 KSCrash的源码来进行分析

Dsym

debugging SYMbols:调试符号表

当我们build的时候,就会在.app文件中同时生成一个 Dsym 文件,我们在后期捕获到线上 Crash 或者 卡顿 堆栈的地址信息时,会结合 Dsym 进行符号还原,进而确认卡顿、崩溃的具体位置

ASLR

这个在 趣探 Mach-O:文件格式分析 这篇文章中也有提到,这里再深入阐述一下。

ASLR:Address space layout randomization,将可执行程序随机装载到内存中,这里的随机只是偏移,而不是打乱,具体做法就是通过内核将 Mach-O 的段“平移”某个随机系数

我们再来看一下crash堆栈信息

我们先关注第三列,这个是函数调用完的返回地址,我们也叫做Frame Pointer Addreass。第四列,是共享对象的的起始地址(Base address of shared object,下面叫做基地址,比如上面的 UIKit)

在终端下,如果我们配合 Dsym 进行符号解析的话,需要这样子写指令

可以发现仅仅依靠 Frame Pointer 和 Dsym 并不能够进行符号化解析,还需要基地址的配合。为什么呢?

因为ASLR 引入了一个 slide(偏移),可以通过dyld_get_image_vmaddr_slide() 来进行获取,函数对应在符号表的地址、slideframe Pointer address满足下面这个公式。slide可以通过程序的 api 获取,也可以通过 Dsym 文件拿到

Dl_info

我们一会经过 dladdr()处理后的有效信息都会放进这个结构体中

  • fname:路径名,例如

  • dli_fbase:刚才讲到的共享对象的的起始地址(Base address of shared object,下面叫做基地址,比如上面的 CoreFoundation)
  • dli_saddr :符号的地址
  • dli_sname:符号的名字,即下面的第四列的函数信息

LC_SYMTAB

符号表在 Mach-O目标文件中的地址可以通过LC_SYMTAB加载命令指定的 symoff找到,对应的符号名称在stroff,总共有nsyms条符号信息

nlist

nlist的数据结构看似比较简单,但是里面具有很多的学问,这里先只简单介绍一下它的数据结构,足够我们接下来的分析源码即可

符号解析

符号解析基本思路如下

  • 根据 Frame Pointer 拿到函数调用的地址(address)
  • 寻找包含地址 (address) 的目标镜像(image)
  • 拿到镜像文件的符号表、字符串表
  • 根据 address 、符号表、字符串表的对应关系找到对应的函数名

下面分析的主要是ksdl_dladdr函数

首先根据 address,找到目标镜像

后面两步骤是关键