crash堆栈
1 | Thread 32 Crashed: |
源码
1 | + (NSDictionary *)getImageInfo:(const mach_header_t *)header path:(const char *)path targetSlide:(long)targetSlide validate:(BOOL)validate { |
crash现场还原
1 | 0 _demo_ 0x0000000101a43854 0x1006ac000 + 20543572 +[xxx getImageInfo:path:targetSlide:validate:] |
- 计算偏移量
0x0000000101a43854 - 0x1006ac000 = 20543572
- 在xcode调试控制台 获取ipa包的 载入地址
image list demo
1 | (lldb) image list _demo_ |
- 计算实际地址,设置断点
0x00000001000e0000 + 20543572 = 0x0000000101477854
1 | breakpoint set -a 0x0000000101477854 |
分析寄存器与变量之间的对应关系
进入断点后,进行进一步的分析。
1 | _demo_`+[xxx getImageInfo:path:targetSlide:validate:]: |
此处,正在读取 x26 + 0x4 的值,对应代码:
1 | image->cputype = header->cputype; |
沿着数据流向分析:1
2
3
4x26 来自 x2,
x2 为第1个参数 header;
x3 为第2个参数 path;
x23 来自 循环遍历 _dyld_get_image_header(int i) 的计数器 i
从 crash 报告的保留 register 来看:
1 | Thread 32 crashed with ARM-64 Thread State: |
几个重要的参数 x2, x26, x3 均为 0x0, 说明从 dyld_xxx 返回的数据有问题,而 x24 保留有 loop count,说明这个值是异常的
经过测试,给 dyld_xxx 使用一个特别大的值越界之后返回的正是 0x0, 说明 image 在动态增加的时候这个接口是不安全的,有可能导致在另外一个线程当中读取出来 0x0的数据,就会造成 crash,这里由于没有办法同步知道这些 image 的加载变更,所以需要判断 header, path 等参数是否为 null 进行简单校验。