作者:林蓝东
最近的一个手机 QQ 版本发出去后收到比较多关于 CoreMotion 的 crash 上报,案发现场如下:
但是看看这个堆栈发现它完全不按照套路出牌啊!
乍一看是挂在 CoreMotion
里面的CLStartStopAdvertisingBeacon
函数,看似是 iBeacon 相关的问题,但实际上是具体函数的符号解不出来,注意 CLStartStopAdvertisingBeacon + 175940
这个巨大的偏移量,一般的函数不可能这么大,所以这个地址对应的肯定是另外的一个函数!
抛开错误的函数名,看看堆栈的调用顺序,看上去是像是 CoreMotion
在子线程起了一个 Runloop,然后在这个 Runloop 处理来自 IOKit 的回调。
再看看 crash 的 Exception Codes: BUS_ADRALN at 0x006575716572205d
,可以知道这是访问了一个未对齐的地址 0x006575716572205d
导致的崩溃;同时留意到上报上来的寄存器状态,这个地址正是当前 pc
和 x8
寄存器的值!:
一般 PC
寄存器保存的是下一条指令的地址,并且要求地址最后的两个比特位是 00
,这个地址很明显不能满足要求;这种情况通常是因为数据被破坏,导致读取到的函数指针值异常。
有了上面几点发现,我们可以到真机上去探一探究竟。这个上报上来的 crash 是发生在安装了 iOS 10.3.1 (14E304
的一台 64 位机器上,所以我们找来一台符合这两个条件的设备;因为这是发生在系统框架里面,满足这两个条件才能保证 CoreMotion
的二进制内容和 crash 的机器是一致的(可以通过 framework 的 UUID 来验证这一点)。
在真机上我们要去找到这几个解错的函数名,而我们的依据就是下图中红色框的地址:
这些是 crash 所在指令的地址,但这些地址由于 ASLR(地址空间配置随机载入) 的原因是不固定的,所以我们不能在自己的机器上直接用这些地址,而是要利用 crash 时