谈谈iOS获取调用链 (3)

上面代码便会从下到上依次打印出调用栈函数中的地址,这个地址总是在函数调用地方的下一个地址,我们就需要拿这个地址还原出对应的符号名称。

5、恢复线程thread_resume thread_resume(main_thread); 6、还原符号表

这一步主要是将已经获得的调用链上的地址分别解析出对应的符号。主要是参考了运行时获取函数调用栈 的方法,其中用到的dyld链接mach-o文件的基础知识,后续会专门针对这里总结一篇文章。

enumerateSegment(header, [&](struct load_command *command) { if (command->cmd == LC_SYMTAB) { struct symtab_command *symCmd = (struct symtab_command *)command; uint64_t baseaddr = 0; enumerateSegment(header, [&](struct load_command *command) { if (command->cmd == LC_SEGMENT_64) { struct segment_command_64 *segCmd = (struct segment_command_64 *)command; if (strcmp(segCmd->segname, SEG_LINKEDIT) == 0) { baseaddr = segCmd->vmaddr - segCmd->fileoff; return true; } } return false; }); if (baseaddr == 0) return false; nlist_64 *nlist = (nlist_64 *)(baseaddr + slide + symCmd->symoff); uint64_t strTable = baseaddr + slide + symCmd->stroff; uint64_t offset = UINT64_MAX; int best = -1; for (int k = 0; k < symCmd->nsyms; k++) { nlist_64 &sym = nlist[k]; uint64_t d = pcSlide - sym.n_value; if (offset >= d) { offset = d; best = k; } } if (best >= 0) { nlist_64 &sym = nlist[best]; std::cout << "SYMBOL: " << (char *)(strTable + sym.n_un.n_strx) << std::endl; } return true; } return false; }); 参考

函数调用栈空间以及fp寄存器

函数调用栈

也谈栈和栈帧

运行时获取函数调用栈

深入解析Mac OS X & iOS 操作系统 学习笔记

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfspx.html