前言
- [NSThread callStackSymbols]只能获取当前线程的调用栈,无法获取其他线程的调用栈
- 获取所有线程的调用栈,主要参考自KSCrash这个框架。有能力的同学可以深入研究一下
正文开始
步骤
一、获取函数地址
通过task_threads获取所有线程,并通过thread_get_state获取线程调用栈,进而获取当前线程所有的函数地址
二、定位镜像
dyld提供了镜像相关的接口,如获取镜像数量_dyld_image_count、名称_dyld_get_image_name及其地址_dyld_get_image_header,通过镜像地址就可以获取Mach-O相关的信息Mach-O中的Mach64 Header中包含了Load Commands数量,Load Commands加载命令中包含了LC_SEGMENT_64,该加载命令数据结构包含了命令名称Command、虚拟地址VM Address及其大小VM Size,因此可以通过遍历获取LC_SEGMENT_64中的各个段的虚拟起始地址及其范围,就可以比较来定位是否在该段中,进而就可以确定是否在该镜像中
三、查找符号
通过LC_SYMTAB加载命令获取符号表及字符串表的信息,如地址、数量及大小,就可以获取符号表中的所有符号及字符串表中对应的函数名称
四、定位符号
通过遍历符号表中的所有符号地址来匹配与当前函数地址最接近的,即为要寻找的函数符号,并通过符号表中的String Table Index字符串表偏移量来获取函数符号名称