单板软件Linux内核出现crash,如何采用GDB工具进行调试? 基本方法过程如下:
1. 为了测试GDB操作,故意在kernel/linux/fs/ioctl.c文件的do_vfs_ioctl方法中加入空指针操作代码,然后编译image烧入单板,启动单板,内核crash,部分log如下:
CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 800a73b8, ra == 800a793c
Oops[#1]:
Cpu 0
$ 0 : 00000000 10008d00 00000000 ffffffea
$ 4 : fffffdfd 10008d01 00000001 00000000
$ 8 : 00000000 7fed2e40 00001cb2 00000b3b
$12 : 00031c7f 2ab5ead7 2aaac7c9 15010000
$16 : 7fed2e18 878ca5a0 00000000 00000001
$20 : 2ab84980 00000000 00000007 00000000
$24 : 00000000 2ab62090
$28 : 8782c000 8782fe98 7fed2fc8 800a793c
Hi : 0000002a
Lo : 000311fc
epc : 800a73b8 do_vfs_ioctl+0x88/0x5c8
Not tainted
ra : 800a793c sys_ioctl+0x44/0x98
Status: 10008d03 KERNEL EXL IE
Cause : 00000008
BadVA : 00000000
PrId : 0002a080 (Broadcom4350)
Modules linked in:
Process init (pid: 1, threadinfo=8782c000, task=8782bb68, tls=00000000)
Stack : 878ca1a0 00000004 00000000 10008d00 00000603 2aabcfff 87b0bea8 00000001
87beeaf0 2aabc000 2aabd000 87aa9cb0 2aabd000 2aabd000 8782ff08 fffffff8
00000001 7fed3258 00000007 00000000 878ca5a0 0000540d 00000000 00000001
2ab84980 800a793c 08100871 00000001 87bea41c 0000fff2 00000000 2abbdff0
7fed2e18 00000001 7fed2e60 2abbdff0 00000120 8001ba7c 00000000 00000000
...
Call Trace:(--Raw--
[<800a793c>] sys_ioctl+0x44/0x98
[<8001ba7c>] stack_done+0x20/0x3c
Call Trace:
[<800a73b8>] do_vfs_ioctl+0x88/0x5c8
[<800a793c>] sys_ioctl+0x44/0x98
[<8001ba7c>] stack_done+0x20/0x3c
Code: 0c029c9f 02003021 8fbf0064 <8c020000> 8fb40060 8fb3005c 8fb20058 8fb10054 8fb00050
Disabling lock debugging due to kernel taint
Kernel panic - not syncing: Attempted to kill init!
Rebooting in 1 seconds..<6>
stopping CPU 1
kerSysMipsSoftReset: called on cpu 0
Cpu 0
$ 0 : 00000000 10008d00 00000000 ffffffea
$ 4 : fffffdfd 10008d01 00000001 00000000
$ 8 : 00000000 7fed2e40 00001cb2 00000b3b
$12 : 00031c7f 2ab5ead7 2aaac7c9 15010000
$16 : 7fed2e18 878ca5a0 00000000 00000001
$20 : 2ab84980 00000000 00000007 00000000
$24 : 00000000 2ab62090
$28 : 8782c000 8782fe98 7fed2fc8 800a793c
Hi : 0000002a
Lo : 000311fc
epc : 800a73b8 do_vfs_ioctl+0x88/0x5c8
Not tainted
ra : 800a793c sys_ioctl+0x44/0x98
Status: 10008d03 KERNEL EXL IE
Cause : 00000008
BadVA : 00000000
PrId : 0002a080 (Broadcom4350)
Modules linked in:
Process init (pid: 1, threadinfo=8782c000, task=8782bb68, tls=00000000)
Stack : 878ca1a0 00000004 00000000 10008d00 00000603 2aabcfff 87b0bea8 00000001
87beeaf0 2aabc000 2aabd000 87aa9cb0 2aabd000 2aabd000 8782ff08 fffffff8
00000001 7fed3258 00000007 00000000 878ca5a0 0000540d 00000000 00000001
2ab84980 800a793c 08100871 00000001 87bea41c 0000fff2 00000000 2abbdff0
7fed2e18 00000001 7fed2e60 2abbdff0 00000120 8001ba7c 00000000 00000000
...
Call Trace:(--Raw--
[<800a793c>] sys_ioctl+0x44/0x98
[<8001ba7c>] stack_done+0x20/0x3c
Call Trace:
[<800a73b8>] do_vfs_ioctl+0x88/0x5c8
[<800a793c>] sys_ioctl+0x44/0x98
[<8001ba7c>] stack_done+0x20/0x3c
Code: 0c029c9f 02003021 8fbf0064 <8c020000> 8fb40060 8fb3005c 8fb20058 8fb10054 8fb00050
Disabling lock debugging due to kernel taint
Kernel panic - not syncing: Attempted to kill init!
Rebooting in 1 seconds..<6>
stopping CPU 1
kerSysMipsSoftReset: called on cpu 0
Kernel hacking --->
[*] Kernel debugging
[*] Compile the kernel with debug info
编译内核命令:make kernelbuild,要在project的根目录下运行该命令进行编译。
启动GDB命令如下:
[myname@localhost bin]$ ./mips-linux-uclibc-gdb
(gdb) file /opt/mydir/kernel/linux/vmlinux
3. GDB调试定位
Checked call trace log, the most important part in log is “epc” (exception program counter), it is where the crash happened. In this example, the “epc” is 0xc0d1d488. For X1000 and X3500, the address like 0x8XXXXXXXX is in kernel, and the address like 0xcXXXXXXX is in some module.
地址0x800a73b8就是对应于地址(do_vfs_ioctl+0x88),后者表示位于函数do_vfs_ioctl的偏移地址0x88处。
调试过程如下:
(gdb) list *(0x800a73b8)
0x800a73b8 is in do_vfs_ioctl (fs/ioctl.c:569).
564 error = vfs_ioctl(filp, cmd, arg);
565 break;
566 }
567 error = *test;
568 return error;
569 }
570
571 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
572 {
573 struct file *filp;
(gdb) list*(do_vfs_ioctl+0x88)
0x800a73b8 is in do_vfs_ioctl (fs/ioctl.c:569).
564 error = vfs_ioctl(filp, cmd, arg);
565 break;
566 }
567 error = *test;
568 return error;
569 }
570
571 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
572 {
573 struct file *filp;
(gdb) list*(sys_ioctl+0x44)
564 error = vfs_ioctl(filp, cmd, arg);
565 break;
566 }
567 error = *test;
568 return error;
569 }
570
571 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
572 {
573 struct file *filp;
(gdb) list*(do_vfs_ioctl+0x88)
0x800a73b8 is in do_vfs_ioctl (fs/ioctl.c:569).
564 error = vfs_ioctl(filp, cmd, arg);
565 break;
566 }
567 error = *test;
568 return error;
569 }
570
571 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
572 {
573 struct file *filp;
(gdb) list*(sys_ioctl+0x44)
可以分析该函数附近代码发现错误位置在line567,test为空指针(故意在前面赋值NULL)。