1. 查看崩溃前内核日志
智慧屏内核崩溃时,在/data/vendor/log/mtklog/aee_exp/history.log中会记录发生panic的时间点,如下图所示:
从图中可以看出,在2021-09-29 18:30:22时发生kernel panic,对应崩溃前的内核日志保存在20210929183022-12999199目录下的last_kmsg文件中
打开last_kmsg文件,搜索panic附近的日志,可以看到有如下提示:
即在zram_bvec_rw函数0xb58偏移处出现异常,那么接下来要解析zram_bvec_rw函数0xb58偏移处的代码行。
2. 解析函数栈
在CDE代码搜索中查找zram_bvec_rw函数,该函数在kernel中,所以需要找kernel的符号表文件。
(1)根据版本的构建时间在工程者桌面获取版本路径
在版本路径中有vmlinux,这个文件就是内核符号表文件
(2)设置llvm-symbolizer的环境变量
llvm-symbolizer、llvm-nm位于如下目录:
prebuilts/clang/host/linux-x86/clang-r383902b/bin,
为了方便在其他目录也能使用这个工具,把这个目录加入到环境中,执行如下命令:
export PATH=/home/lw/code/dnte/master/chip/prebuilts/clang/host/linux-x86/clang-r383902b/bin:$PATH
(3)解析函数的实际地址
llvm-nm命令可以列出内核中所有函数的地址,用如下命令可以获取zraw_bvec_rw函数在内核中的地址:
llvm-nm vmlinux |grep zraw_bvec_rw
(4)解析代码行
在内核日志中,出现问题的地方是该函数的0xb58偏移,如下日志:
那么计算真正的地址:0xffffff8008b211cc + 0xb58 = 0xffffff8008b21d24
用llvm-symbolizer工具计算出真正的代码行:
从命令执行的结果看,zram_drv.c的2117行代码异常导致了这次的内核panic,至此就能容易分析出内核崩溃的根因。
后来经过分析,该问题的根因是kmap_atomic和kunmap_atomic函数的调用不匹配导致的,kmap_atomic函数中禁用了抢占但未打开,导致zs_map_object函数内部BUG_ON检查失败,引发panic重启。