oops
~ # insmod /mnt/oops.ko
[ 117.135066] oops: loading out-of-tree module taints kernel.
[ 117.142239] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[ 117.142564] Mem abort info:
[ 117.142679] ESR = 0x96000046
[ 117.142812] Exception class = DABT (current EL), IL = 32 bits
[ 117.142991] SET = 0, FnV = 0
[ 117.143114] EA = 0, S1PTW = 0
[ 117.143242] Data abort info:
[ 117.143364] ISV = 0, ISS = 0x00000046
[ 117.143494] CM = 0, WnR = 1
[ 117.143651] user pgtable: 4k pages, 39-bit VAs, pgdp = (____ptrval____)
[ 117.143853] [0000000000000000] pgd=000000005984f003, pud=000000005984f003, pmd=0000000000000000
[ 117.144482] Internal error: Oops: 96000046 [#1] PREEMPT SMP
[ 117.144744] Modules linked in: oops(O+)
[ 117.145175] CPU: 1 PID: 1202 Comm: insmod Tainted: G O 5.0.0-gadef409-dirty #308
[ 117.145542] Hardware name: linux,dummy-virt (DT)
[ 117.145825] pstate: 40000005 (nZcv daif -PAN -UAO)
[ 117.146198] pc : hello_init+0x1c/0x1000 [oops]
....
Segmentation fault
查看log,定位到pc指针
pc : hello_init+0x1c/0x1000 [oops]
关于func+0x##/0x####的定位解读:形如 函数+偏移/长度
func指示了异常函数名
0x##表示出错的偏移位置
0x####表示func函数的大小
如果系统没有重启,查看驱动加载地址
~ # cat /sys/module/oops/sections/.init.text
0xffffff8008aa5000
使用gdb加载ko文件
aarch64-linux-gnu-gdb oops.ko
(gdb) file vmlinux ----->加载内核镜像文件
Load new symbol table from "vmlinux"? (y or n) y
Reading symbols from vmlinux...done.
(gdb) add-symbol-file oops.o 0xffffff8008aa5000 -----> 手工加载文件
add symbol table from file "oops.o" at
.text_addr = 0xffffff8008aa5000
(y or n) y
Reading symbols from oops.o...done.
(gdb) disassemble hello_init
Dump of assembler code for function hello_init:
0x0000000000000000 <+0>: stp x29, x30, [sp, #-16]!
0x0000000000000004 <+4>: mov x29, sp
0x0000000000000008 <+8>: mov x0, x30
0x000000000000000c <+12>: bl 0xc <hello_init+12>
0x0000000000000010 <+16>: mov x1, #0x0 // #0
0x0000000000000014 <+20>: mov w2, #0x1 // #1
0x0000000000000018 <+24>: mov w0, #0x0 // #0
0x000000000000001c <+28>: str w2, [x1]
0x0000000000000020 <+32>: ldp x29, x30, [sp], #16
0x0000000000000024 <+36>: ret
End of assembler dump.
(gdb)
定位到0x000000000000001c <+28>: str w2, [x1]
本人测试时 (gdb) add-symbol-file oops.o 0x0000000000000000 加载到0x0000000000000000也可以定位到0x1c的位置
是不是觉得太麻烦?直接l指令定位查看出错位置。无需file vmlinux
(gdb) l *(hello_init+0x1c)
0x1c is in hello_init (/xxx/oops.c:9).
4
5 static int __init hello_init(void)
6 {
7 int *p = 0;
8
9 *p = 1;
10
11 return 0;
12 }
13
注意这个只是定位出错的地方,不代表修改点,对于复杂的问题无法一眼就可看出
不想用gdb?使用objdump反汇编
aarch64-linux-gnu-objdump -S oops.o
oops.o: file format elf64-littleaarch64
Disassembly of section .init.text:
0000000000000000 <init_module>:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init(void)
{
0: a9bf7bfd stp x29, x30, [sp, #-16]!
4: 910003fd mov x29, sp
8: aa1e03e0 mov x0, x30
c: 94000000 bl 0 <_mcount>
int *p = 0;
*p = 1;
10: d2800001 mov x1, #0x0 // #0
14: 52800022 mov w2, #0x1 // #1
return 0;
}
18: 52800000 mov w0, #0x0 // #0
*p = 1;
1c: b9000022 str w2, [x1]
}
20: a8c17bfd ldp x29, x30, [sp], #16
24: d65f03c0 ret
Disassembly of section .exit.text:
0000000000000000 <cleanup_module>:
{
0: d65f03c0 ret