linux at模块,使用kgdb调试linux内核及内核模块

EOF

#chmod +x debugkernel

这个脚本主要是调用gdbstart程序设置target机上使用的串口及其速率,并使内核处于调试状态

3.3 开始调试

target上的内核或内核模块处于调试状态时,可以查看其变量、设置断点、查看堆栈等,并且是源码级的调试,和用gdb调试用户程序一样

3.3.1 内核启动后调试

*在target机器上

重启系统,选择以 2.4.23-kgdb内核启动,启动完成后运行debugkenel,这时内核将停止运行,在控制台屏幕上显示信息,并等待来自developer的串口连接

#./debug

About to activate GDB stub in the kernel on /dev/ttyS1

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);

这时target上的内核处于调试状态,可以查看其变量、设置断点、查看堆栈等,和用gdb调试用户程序一样

查看堆栈

(gdb) bt

#0  breakpoint () at kgdbstub.c:1005

#1  0xc0387f48 in init_task_union ()

#2  0xc01bc867 in gdb_interrupt (irq=3, dev_id=0x0, regs=0xc0387f98) at

gdbserial.c:158

#3  0xc010937b in handle_IRQ_event (irq=3, regs=0xc0387f98, action=0xce5a9860)

at irq.c:452

#4  0xc0109597 in do_IRQ (regs=

{ebx = -1072671776, ecx = -1, edx = -1070047232, esi = -1070047232, edi

= -1070047232, ebp = -1070039092, eax = 0, xds

= -1070071784, xes = -1070071784, orig_eax = -253, eip = -1072671729, xcs =

16, eflags = 582, esp = -1070039072, xss = -1072671582}) at irq.c:639

#5  0xc010c0e8 in call_do_IRQ ()

查看jiffies变量的值

(gdb) p jiffies

$1 = 76153

如果想让target上的内核继续运行,执行continue命令

(gdb) continue

Continuing.

3.3.2 内核在引导时调试

kgdb可以在内核引导时就对其进行调试,但并不是所有引导过程都是可调试的,如在kgdb 1.9版中,它在init/main.c的start_kernel()函数中插入以下代码:

start_kernel()

{

......

smp_init();

#ifdef CONFIG_KGDB

if (gdb_enter) {

gdb_hook();             /* right at boot time */

}

#endif

......

}

所以在smp_init()之前的初始化引导过程是不能调试的。

另外要想让target的内核在引导时就处于调试状态,需要修改其/etc/grub.conf文件为如下形式:

title Red Hat Linux (2.4.23-kgdb)

root (hd0,0)

kernel /boot/vmlinuz-2.4.23-kgdb ro root=/dev/hda1 gdb gdbttyS=1 gdbbaud=115200

*在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处被暂停。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值