有些模块类KE,需要由对应模块owner处理,但是有时从程序流程可能看不出具体原因,这时就需要掌握简单的KE分析基础。
gdb是开源调试工具,可以在网上搜到很多信息,在此列出Windows环境下分析KE必要步骤,仅供参考。
打开GAT安装路径下的prebuilt\python\bin\aarch64-linux-android-gdb.exe调试64 bit kernel。
如果要调试32bit kernel则使用arm-linux-androideabi-gdb.exe
【KE.dbg路径如下:】
data/aee_exp ;
mtklog/aee_exp ;
mtklog/aee_expbackup
注意:如果开不了机,从uart log中发现有KE问题导致的重启,需要回读expdb分区。
参考[FAQ19639] How to readback expdb。
【vmlinux路径如下:】
alps/out/target/product/$Projectname/obj/KERNEL_OBJ/vmlinux
注意:要同一次编译生成,参考[FAQ06985]KE发生后如何判断vmlinux和log是否匹配。
(1)cd 解开的DB路径,如fatal.00.KE.dbg.DEC
(2)file vmlinux所在路径
(3)core SYS_MINI_RDUMP所在路径,在(1)中已经cd过,所以就是当前路径
(gdb) cd D:\fatal.00.KE.dbg.DEC
Working directory D:\fatal.00.KE.dbg.DEC.
(gdb) file symbols/vmlinux
Reading symbols from symbols/vmlinux...done.
(gdb) core SYS_MINI_RDUMP
warning: core file may not match specified executable file.
Core was generated by `console=tty0 console=ttyMT0,921600n1 root=/dev/ram vmalloc=496M androidboot.har'.
#0 slab_alloc_node (addr=, node=, gfpflags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2512
2512 /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c: No such file or directory.
[Current thread is 1 (LWP 101)]
主要思路如下:
一方面怀疑是客制化code,一方面怀疑可能是函数跳转地址异常。这里会用到命令:bt。
(gdb) bt
#0 slab_alloc_node (addr=, node=, gfpflags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2512
#1 slab_alloc (addr=, gfpflags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2560
#2 kmem_cache_alloc (s=0x1 <__vectors_start>, gfpflags=3233115096)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2565
#3 0xc0813bc8 in kmem_cache_alloc_node (node=, flags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/include/linux/slab.h:304
(gdb) f 0
#0 slab_alloc_node (addr=, node=, gfpflags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2512
2512 in /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c
(gdb) disas
Dump of assembler code for function kmem_cache_alloc:
0xc01396e4 <+0>: mov r12, sp
0xc01396e8 <+4>: push {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr, pc}
0xc01396ec <+8>: sub r11, r12, #4
0xc01396f0 <+12>: sub sp, sp, #28
0xc01396f4 <+16>: mov r12, sp
0xc01396f8 <+20>: bic r12, r12, #8128 ; 0x1fc0
0xc01396fc <+24>: movw r8, #18296 ; 0x4778
0xc0139700 <+28>: bic r9, r12, #63 ; 0x3f
0xc0139704 <+32>: movt r8, #49369 ; 0xc0d9
0xc0139708 <+36>: mov r7, lr
0xc013970c <+40>: mov r6, r0
0xc0139710 <+44>: mov r5, r1
0xc0139714 <+48>: str r12, [r11, #-48] ; 0xffffffd0
0xc0139718 <+52>: mov r0, #1
0xc013971c <+56>: bl 0xc004df08
0xc0139720 <+60>: ldr r4, [r6]
0xc0139724 <+64>: bl 0xc02a3a14
0xc0139728 <+68>: ldr r10, [r8, r0, lsl #2]
0xc013972c <+72>: add r3, r4, r10
=> 0xc0139730 <+76>: ldr r3, [r3, #4]; 程序挂在这里
(gdb) i reg //查看所有寄存器值
r0 0x1 1
r1 0xc0b56bd8 3233115096
r2 0xc0813bc8 3229694920
r3 0xa0d14a00 2698070528
r4 0xc0d6ea00 3235310080
r5 0x4d0 1232
r6 0xdb401e00 3678412288
r7 0xc0813bc8 3229694920
r8 0xc0d94778 3235465080
r9 0xd92f0000 3643736064
r10 0xdffa6000 3757727744
r11 0xd92f1ccc 3643743436
r12 0x1 1
sp 0xd92f1c88 0xd92f1c88
lr 0xc02a3a34 3223992884
pc 0xc0139730 0xc0139730
cpsr 0x200f0013 537853971
(gdb) i reg $r3 $r4 //只看r3和r4
r3 0xa0d14a00 2698070528
r4 0xc0d6ea00 3235310080
此时结合C code和汇编找出异常寄存器对应的变量,然后查看变量值。这里会用到命令:p 变量名。
(gdb) p s //查看C code中的s变量的值,可惜被编译器优化看不到了。
$1 =
(gdb) up //因此查看上一帧(也可以用f 1来指定当前帧),看传下来s是多少,一直往前追踪
#1 slab_alloc (addr=, gfpflags=, s=)
at /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c:2560
2560 in /mnt/one/bak/PROJECT/MT6753/F2_TMCELL_0208/kernel-3.18/mm/slub.c