*在target机器上
引导2.4.23-kgdb内核,内核将在短暂的运行后暂停并进入调试状态,打印如下信息:
Waiting for connection from remote gdb...
*在developer机器上
#cd /home/liangjian/linux-2.4.23
# gdb vmlinux
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
执行rmt宏
(gdb) rmt
breakpoint () at kgdbstub.c:1005
1005 atomic_set(&kgdb_setting_breakpoint, 0);
查看当前堆栈
(gdb) bt
#0 breakpoint () at kgdbstub.c:1005
#1 0xc0387fe0 in init_task_union ()
#2 0xc01bc984 in gdb_hook () at gdbserial.c:250
#3 0xc0388898 in start_kernel () at init/main.c:443
在do_basic_setup函数处设置断点,并让内核恢复运行
(gdb) b do_basic_setup
Breakpoint 1 at 0xc0388913: file current.h, line 9.
(gdb) continue
Continuing.
[New Thread 1]
[Switching to Thread 1]
Breakpoint 1, do_basic_setup () at current.h:9
9 __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
内核在do_basic_setup断点处停止运行后查看当前堆栈
(gdb) bt
#0 do_basic_setup () at current.h:9
(gdb)
3.3.3 内核模块调试调试
要想调试内核模块,需要相应的gdb支持,kgdb的主页上提供了一个工具gdbmod,它修正了gdb 6.0在解析模块地址时的错误,可以用来正确的调试内核模块
*在developer机器上
写了个测试用的内核模块orig,如下:
void xcspy_func()
{
printk("<1>xcspy_func\n");
printk("<1>aaaaaaaaaaa\n");
}
int xcspy_init()
{
printk("<1>xcspy_init_module\n");
return 0;
}
void xcspy_exit()
{
printk("<1>xcspy_cleanup_module\n");
}
module_init(xcspy_init);
module_exit(xcspy_exit);
编译该模块:
#cd /home/liangjian/lkm
#gcc -D__KERNEL__ -DMODULE -I/home/liangjian/linux-2.4.23/include -O -Wall -g -c -o orig.o orig.c
#scp orig.o root@192.168.16.30:/root
开始调试:
# gdbmod vmlinux
GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
设置符号文件的搜索路径
(gdb) set solib-search-path /home/liangjian/lkm
执行rmt宏
(gdb) rmt
breakpoint () at kgdbstub.c:1005
1005 atomic_set(&kgdb_setting_breakpoint, 0);
设置断点使得可以调试内核模块的init函数,查内核源码可知,内核是通过module.c文件的第566行(sys_init_module函数中)mod->init来调用模块的init函数的
(gdb) b module.c:566
Breakpoint 1 at 0xc011cd83: file module.c, line 566.
(gdb) c
Continuing.
[New Thread 1352]
[Switching to Thread 1352]
这时在target机器上执行insmod orig.o,developer则相应的在断点处被暂停,如下
Breakpoint 1, sys_init_module (name_user=0xc03401bc "\001",
mod_user=0x80904d8) at module.c:566
566 if (mod->init && (error = mod->init()) != 0) {
使用step命令进入模块的init函数
(gdb) step
xcspy_init () at orig.c:12
12 printk("<1>xcspy_init_module\n");
(gdb) n
15 }
(gdb)
说明:
调试内核模块的非init函数相对比较简单,只要先在target上执行insmod orig.o,这时由于模块的符号被加载,可以直接在developer的gdb中对想调试的模块函数设置断点,如bt xcspy_func,后面当xcspy_func被调用时就进入了调试状态。
如果想调试内核模块的init函数,由于在执行insmod之前模块的符号还没有被加载,不能直接对模块的init函数设置断点,所以相对来说要困难一些。可以采用两种变通的方法:1,采用上面介绍的在内核调用模块的init函数被调用之前的某处插入断点,如bt sys_init_module()或bt module.c:566;2,在developer上让内核处于运行状态,在target上先执行一遍insmod orig.o,这时orig.o的符号已经被加载到内存中,可以直接在developer的gdb中对模块的init函数设置断点,如bt xcspy_init,然后在target上rmmod orig.o,当下次在target上重新加载orig.o时就进入了调试状态,developer在xcspy_init处被暂停。
| 基于Linux操作系统实现的传真系统 | 12-09 | |
| Linux操作系统上最好的10款开源游 | 11-20 | |
| Linux 系统中的超级权限的控制 | 11-09 | |
| Linux操作系统下的常见系统资源共 | 11-07 | |
| Linux下的中文显示和支持常见问题 | 10-23 | |
| 嵌入式Linux系统的动态电源管理技 | 10-13 | |
| 从硬盘安装Linux操作系统的方法步 | 10-12 | |
| 深入浅出分析Linux设备驱动程序中 | 10-10 | |
| 使用kgdb调试linux内核及内核模块 | 10-04 | |
| 使用Linux 文本工具简化数据的提 | 10-04 | |
| 如何在Linux操作系统下检测内存泄 | 09-27 | |
| Linux内核编译菜单中相关选项的意 | 09-20 | |