CPU异常捕获
对于野指针、跑飞之类的异常会被MMU拦截并报告给CPU,这一系列都是硬件行为,具体请看:
- MediaTek On-Line> Quick Start> 深入分析Android native exception框架> 流程-异常处理
- 在上面章节里的内核异常处理流程,有一处不同,走到arm_notify_die()后,判断是kernel mode就直接调用die()了,而不是force_sig_info()
这类问题比较难定位,也是占KE比例的大头,原因通常是内存被踩坏、指针use atfer free等多种因素,在当时可能不会立即出现异常,而是到使用这块内存才有可能崩溃。
分析问题的手段也是多样化,比如用watch point,MMU protect或加debug code等(请参考附录FAQ)
软件异常捕获
在kernel代码里,一般会通过BUG(),BUG_ON(),panic()来拦截超出预期的行为,这是软件主动回报异常的功能。
这些问题分析通常有固定的套路,请参考后面的:《实例篇: 案例分析》
BUG()/BUG_ON()实现
在内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。使用方式如下
if (condition)
BUG();
或者 :
BUG_ON(condition); //只是在BUG基础上多层封存而已:
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
32bit kernel:
BUG() 的实现采用了埋入未定义指令(0xE7F001F2,记住这个值,log里看到这个值,你就应该知道是调用了BUG()/BUG_ON()了)的方式
64bit kernel:
原生的kernel,BUG()是直接调用panic()的:
不过Mediatek修改了BUG()的实现,这样有更多的调试信息输出(die()有寄存器等信息输出)
当你看到如下log时,就应该知道是BUG()/BUG_ON()引起的了!
[ 147.234926]<0>-(0)[122:kworker/u8:3]Unable to handle kernel paging request at virtual address 0000dead