找回密码
 会员注册
查看: 13|回复: 0

手把手教你Debug—iOS14ImageIOCrash分析

[复制链接]

2万

主题

0

回帖

7万

积分

超级版主

积分
73548
发表于 2024-10-1 10:14:17 | 显示全部楼层 |阅读模式
作者:字节移动技术——陈奕背景去年 9 月份开始,许多用户升级到 iOS 14 之后,线上出现很多 ImageIO 相关堆栈的 Crash 问题,而且公司内几乎所有的 APP 上都有出现,在部分 APP上甚至达到了 Top 3 Crash。得益于 APM 平台精准数据采集机制和丰富的异常信息现场,我们通过收集到详细的 Crash 日志信息进行分析解决。问题定位堆栈信息从堆栈信息看,是在 ImageIO 解析图片信息的时候 Crash ,并且最后调用的方法都是看起来都是和 INameSpacePrefixMap 相关,推测 Crash 应该是和这个方法 CGImageSourceCopyPropertiesAtIndex 的实现有关。问题聚合特点机型集中在 iOS14 以上的版本,同时是在后台出现img分析从 CrashLog 做一个初步分析img从堆栈信息看,这段代码是图片库在子线程通过 CGImageSourceCopyPropertiesAtIndex 解析 imageSource 中的图片相关信息,然后发生了野指针的 Crash。CGImageSourceCopyPropertiesAtIndex 的输入只有一个 imageSource,imageSource 由图片的 data 生成,调用栈并没有多线程操作,可以排除是多线程操作 imageSource、data 导致的 Crash。看堆栈是在解析 PNG 图片,通过将下发的图片格式换成 JPG 格式,发现量级并没有降低。推测 Crash 不是某种特定图片格式引起的。反汇编分析反汇编准备iOS 14.3 的 iPhone 8ImageIO 系统库:~/Library/Developer/Xcode/iOS DeviceSupport目录下找到对应 iOS 14.3 的 ImageIO一份 iOS 14.3、iPhone 8 上发生的 CrashLogHopper反汇编1、从 CrashLog 上找到 Crash 对应的指令偏移地址 25550722、通过 Hopper 打开 ImageIO,跳转到指令偏移地址 2555072Navigate => Go To File Offset 25550723、Crash 对应的指令应该是0000000181b09cc0 ldr x8, [x8, #0x10],可以看到应该是访问 [x8, #0x10]指向的内存出错4、查看 Crashlog 中对应寄存器的值,错误地址 far: 0x000021a1ee2fa271,而且 x8 寄存器已经是一个错误的值 0x000021a1ee2fa2615、向上回溯查看 x8 的来源0000000181b09cbc ldr x8, [x20] x8 是存在 x20 指向的内存中(即 x8 = *x20)0000000181b09c98 ldr x20, [x21, #0x8] x20 又存在[x21, #0x8] 指向的内存中0000000181b09c8c adrp x21, #0x1da0ed000,0000000181b09c90 add x21, x21, #0xe10 x21 指向的是一个 data 段,推测 x21 应该是一个全局变量,所以,可能是这个全局变量野了,或者是这个全局变量引用的某些内存(x20)野了6、运行时 debug 查看 x8、x20、x21 对应寄存器的值是什么x21 从内存地址的名字看,应该是一个全局的 MapImageIO`AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap(bool)::sDefaultNameSpacePrefixMap7、从 Hopper 上看,这个sDefaultNameSpacePrefixMap只在AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap(bool) 这个函数中调用。可能会在多线程下调用这个函数,而导致这个全局变量的出现 data race 导致了野指针。__ZZN16AdobeXMPCore_IntL31ManageDefaultNameSpacePrefixMapEbE26sDefaultNameSpacePrefixMap://AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap(bool)::sDefaultNameSpacePrefixMap00000001da0ede10dq0x0000000000000000;DATAXREF=__ZN16AdobeXMPCore_IntL31ManageDefaultNameSpacePrefixMapEb+44,__ZN16AdobeXMPCore_IntL31ManageDefaultNameSpacePrefixMapEb+120,__ZN16AdobeXMPCore_IntL31ManageDefaultNameSpacePrefixMapEb+3928、经过在运行时反复调试,这个AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap(bool) 会在多个方法中调用(并且调用时都加了锁,不太可能会出现 data race):AdobeXMPCore_Int::INameSpacePrefixMap_I::CreateDefaultNameSpacePrefixMap()AdobeXMPCore_Int::INameSpacePrefixMap_I::InsertInDefaultNameSpacePrefixMap(char const*, unsigned long long, char const*, unsigned long long)AdobeXMPCore_Int::INameSpacePrefixMap_I:estroyDefaultNameSapcePrefixMap()9、在后台线程访问访问全局变量 sDefaultNameSpacePrefixMap 时 Crash,推测可能是用户手动杀进程后,全局变量在主线程已经被析构,后台线程还会继续访问这个全局变量,从而出现野指针访问异常。发现 Crash 日志的主线程堆栈也出现 _exit 的调用,可以确定是全局变量析构导致。imgCrash 发生的原因:在用户手动杀进程后,主线程将这个全局变量析构了,这时候子线程再访问这个全局变量就出现了野指针。img复现问题尝试在子线程不断调用 CFDictionaryRef CGImageSourceCopyPropertiesAtIndex(CGImageSourceRef isrc, size_t index, CFDictionaryRef options);,并且手动杀掉进程触发这个 crashimg成功复现img可以证明上述的推理是正确的。总结CFDictionaryRef CGImageSourceCopyPropertiesAtIndex(CGImageSourceRef isrc, size_t index, CFDictionaryRef options); 这个方法在解析部分图片的时候最终会访问全局变量ImageIO`AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap(bool)::sDefaultNameSpacePrefixMap在用户手动杀进程后,这个sDefaultNameSpacePrefixMap被析构,如果这时候在子线程再被访问就可能出现野指针的问题修复 ImageIO Crash 方案因为sDefaultNameSpacePrefixMap 是在系统库内部的全局变量,没办法对其进行修改,只能避免在子线程调用 CGImageSourceCopyPropertiesAtIndex 方法方法一:CGImageSourceCopyPropertiesAtIndex 是用来获取图片的宽高、imageOrientation、动图帧等信息,选择用其他方法来替换,e.g. 宽高用 CGImageRef 来获取方法二:将 CGImageSourceCopyPropertiesAtIndex 被调用的线程收敛起来,调用atexit函数来注册一个进程结束回调函数,进程结束的时候将终止线程关于字节移动平台团队字节跳动移动平台团队(Client Infrastructure)是大前端基础技术行业领军者,负责整个字节跳动的中国区大前端基础设施建设,提升公司全产品线的性能、稳定性和工程效率,支持的产品包括但不限于抖音、今日头条、西瓜视频、火山小视频等,在移动端、Web、Desktop等各终端都有深入研究。就是现在!客户端/前端/服务端/端智能算法/测试开发 面向全球范围招聘!一起来用技术改变世界,感兴趣可以联系邮箱 chenxuwei.cxw@bytedance.com,邮件主题 简历-姓名-求职意向-电话。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-13 07:42 , Processed in 0.600130 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表