关键词: linux驱动,调试,内核
内核编译
设备驱动程序的调试需要内核的支持,因此通常应该根据需要对内核进行重编译。
wuchao@wuchao-VirtualBox:/usr/src/linux-headers-3.2.0-23-generic-pae$sudo make menuconfig |
make menuconfig 需要安装sudoapt-get insatll ncurses-dev,否则出现错误:
***Unable to find the ncurses libraries or the ***required header files. *** ‘makemenuconfig’ requires the ncurses libraries. |
调试工具
Binutils
objdump反汇编,addr2line转换地址到函数名, nm查看符号,gprof分析各个函数使用情况。
make vmlinux 表示对生成的内核镜像不压缩, 生成的内核镜像大约150M。
objdump -Dvmlinux > vmlinux.dis 内核镜像反汇编,生成的vmlinux.dis大约500M。
用内核错误处的ip指针,在vmlinux.dis中搜索,查找执行指令。
printk
printk()会将内核信息输出到内核信息缓冲区中。内核信息缓冲区是一个环形缓冲区(ring buffer),因此,如果塞入的消息过多,就会将之前的消息冲刷掉。通过/proc/sys/kernel/printk文件可以调节printk 的输出等级。
# echo 8 > /proc/sys/kernel/printk |
上面命令可以使得Linux内核的任何printk都被输出。
Gdb/KDB/KGDB
kgdb提供了一种使用 gdb调试 Linux 内核的机制。使用KGDB可以象调试普通的应用程序那样,在内核中进行设置断点、检查变量值、单步跟踪程序运行等操作。使用KGDB调试时需要两台机器,一台作为开发机(Development Machine),另一台作为目标机(Target Machine)。
安装kgdb调试环境需要为Linux内核应用kgdb补丁,补丁实现的gdb远程调试所需要的功能包括命令处理、陷阱处理及串口通讯3个主要的部分。kgdb补丁的主要作用是在Linux内核中添加了一个调试Stub。调试Stub是Linux内核中的一小段代码,提供了运行gdb的开发机和所调试内核之间的一个媒介。gdb和调试stub之间通过gdb串行协议进行通讯。gdb串行协议是一种基于消息的ASCII码协议,包含了各种调试命令。当设置断点时,kgdb负责在设置断点的指令前增加一条trap指令,当执行到断点时控制权就转移到调试stub中去。此时,调试stub的任务就是使用远程串行通信协议将当前环境传送给gdb,然后从gdb处接受命令。gdb命令告诉stub下一步该做什么,当stub收到继续执行的命令时,将恢复程序的运行环境,把对CPU的控制权重新交还给内核。
OOPS/PANIC
oops是内核级(特权级)的Segmentation Fault。
其他调试方法
进程跟踪工具strace
系统性能测试gprof
代码覆盖率测试gcov
core dump
内存泄漏检测工具 valgrind, memwatch
2.6.18编译错误
linux内核2.6.18版本打kdb补丁后编译错误, 不建议使用kdb。 Kdb已经很久没更新,对i686及其他平台也没有支持了。
scripts/mod/sumversion.c: In function ‘get_src_version’:
scripts/mod/sumversion.c:384:16: error: ‘PATH_MAX’ undeclared (first use in this function)
scripts/mod/sumversion.c:384:16: note: each undeclared identifier is reported only once for each function it appears in
scripts/mod/sumversion.c:384:7: warning: unused variable ‘filelist’ [-Wunused-variable]
make[2]: *** [scripts/mod/sumversion.o] Error 1
解决方法:# viscripts/mod/sumversion.c头文件包含中查看是否有limits.h,若没有,包含进去即可,,#inlcude <limits.h>
gcc: 错误: elf_i386:没有那个文件或目录
解决方法:arch/i386/kernel/Makefile文件,把"-m elf_i386" 替换为 "-m32"
drivers/video/sstfb.c:150:6:error: #elif with no expression
解决方法:将#elif 改为#else
kernel/built-in.o:In function `.text.lock.mutex':
mutex.c:(.sched.text+0x17a7):undefined reference to `__mutex_lock_slowpath'
mutex.c:(.sched.text+0x17b1):undefined reference to `__mutex_unlock_slowpath'
make: ***[.tmp_vmlinux1] Error 1
解决方法:将.config文件中的CONFIG_DEBUG_MUTEXES宏值必为y即可。
CONFIG_DEBUG_MUTEXES=y