以前在写驱动的时候 ,遇到比较多的kernel panic oops 问题,然后 问一些 同事 ,比较多的回答都是加 printk,其实用 GDB 的中的一个功能是能很方便地调试这些问题的。 整理了一下,把自己给一家培训学校写的课件 贴上来。 •第一章 调试 • •1.1. 工作环境配置 • •1 )安装好编译用的 kernel-source :RedHat :kernel-devel-xxx.rpm, • suse:kernel-source-xxx.rpm, 自己编译的 kernel source ; •2 ) GCC 包, gcc,g++,cpp, •3) as,ld,objdump,etc •4) glibc/uclibc •5) make •6) gdb •7 ) SSH 工具 : SSH secure Shell 用于 windows 系统与 Linux 系统之间的文件传输 •8 )串口工具,用于调试拿 log 信息, windos 下用超级终端或者 secureCRT , Linux •下用 minicom ,C-Kermit • •1.2 printk •在内核中 printk () 的级别定义: •#define KERN_EMERG "<0>" /* system is unusable */ •#define KERN_ALERT "<1>" /* action must be taken immediately */ •#define KERN_CRIT "<2>" /* critical conditions */ •#define KERN_ERR "<3>" /* error conditions */ •#define KERN_WARNING "<4>" /* warning conditions */ •#define KERN_NOTICE "<5>" /* normal but significant condition */ •#define KERN_INFO "<6>" /* informational */ •#define KERN_DEBUG "<7>" /* debug-level messages */ •通过 /proc/sys/kernel/printk 文件可以调节 printk 的输出级别, •通过如下命令可以使得 Linux 内核的任何 printk 都被输出: •#echo 8 > /proc/sys/kernel/printk •同时设置 grub.conf : •在 Kernel 这一行加上 : console=tty0,console=ttyS0,115200 • •1.3 oops 和 panic •1.3.1 API oops DEBUG • •1.3.1.1. 定位 OOPS •示例: apioops.c: • •#include <stdio.h> •#include <stdlib.h> •Const char array[]="/x6b/xc0 "; •int main(int argc, char *argv[]) •{ • printf("%p/n", array); • *(int *)0 = 0; •} • •1. )编译时打开 complie with debug info 选项 (-g) , 选项 •[root@localhost ~]# gcc -g -o apioops apioops.c • • •2 )执行 api_oops: •[root@localhost ~]# ./apioops • •显示屏输出信息 •0x4005e0 •Segmentation fault •[root@localhost ~]# • •串口输出信息: •apioops[28910]: segfault at 0000000000000000 rip 00000000004004c0 rsp 00007fff22e15760 error 6 •rip 00000000004004c0 : 表示执行到这个位置是 出错 • •EIP RIP 值 一般表示代码运行时 ,出错的位置 • 3 )调试 •[root@localhost ~]# gdb apioops •GNU gdb Fedora (6.8-27.el5) •Copyright (C) 2008 Free Software Foundation, Inc. •License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> •This is free software: you are free to change and redistribute it. •There is NO WARRANTY, to the extent permitted by law. Type "show copying" •and "show warranty" for details. •This GDB was configured as "x86_64-redhat-linux-gnu"... •( gdb ) • •1.list 调试 RIP 地址:很明显 出错在第 11 行 ,访问空指针 •(gdb) l*0x4004c0 •0x4004c0 is in main (apioops.c:11). •6 •7 const char array[] = "/x63/x2e"; •8 int main(int argc, char *argv[]) •9 { •10 printf("%p/n", array); •11 *(int *)0 = 0; •12 } •(gdb) • •2. run apioops ,很明显 11 行 出错 •(gdb) r •Starting program: /root/apioops •0x4005c8 •Program received signal SIGSEGV, Segmentation fault. •0x00000000004004c0 in main (argc=1, argv=0x7fffa7020a28) at oops.c:11 •11 *(int *)0 = 0; •(gdb) • •3) 编译时没打开 complie with debug info 选项 (-g) , 选项的调试,或者只有 error 信息没有 代码的调试 。 •1. 运行 run •(gdb) r •Starting program: /root/apioops •(no debugging symbols found) •(no debugging symbols found) •0x4005c8 •Program received signal SIGSEGV, Segmentation fault. •0x00000000004004c0 in main () •(gdb) • • •2. 反汇编 •( gdb ) disassemble •Dump of assembler code for function main: •0x0000000000400498 <main+0>: push % rbp •0x0000000000400499 <main+1>: mov % rsp,%rbp •0x000000000040049c <main+4>: sub $0x10,%rsp •0x00000000004004a0 <main+8>: mov