红联Linux门户
Linux帮助

用DDD+GDB+QEMU进行Linux内核源码级调试

发布时间:2014-12-16 15:07:34来源:linux网站作者:chenjianhn

在看此文章之前,请先参考《利用busybox制作一个小巧的Linux系统》与《使用busybox做一个小巧的Linux操作系统》制作出一个initrd内存盘。


1. 首先编译内核,编译内核时注意要选中

kernel hacking –> kernel debugging –> compile the kernel with debug info

kernel hacking –> compile the kernel with frame pointers

两个选项。(注意:除此之外kernel hacking 选项下其他的选项都不要选,否则会出现断点无法拦截的情况。)


2. 假设你的内核目录位于/home/xxx/linux-2.6.28中,且编译内核时你指定的大O参数指定的目录是O=/home/xxx/linux-2.6.28-obj。

用新编译的带调试信息的内核,启动一个虚拟机。

$ qemu –kernel /home/xxx/linux-2.6.28-obj/arch/x86/boot/bzImage –append "root=/dev/ram0 rw"

-initrd /home/initrd.gz –s –S [qemu文档:http://qemu.weilnetz.de/qemu-doc.html]

-s-->Shorthand for -gdb tcp::1234, i.e. open agdbserver on TCP port 1234

-S-->Donot start CPU at startup (you must type 'c' in the monitor)

这样启动虚拟机后,它会在1234端口产生一个gdb stub以供调试时使用。

然后我们打开令一个xterm终端运行gdb命令开始调试:

$ gdb /home/xxx/linux-2.6.28-obj/vmlinux


若未使用-s参数,则可按下面启用调试

然后会出现qemu的工作终端,你在上面点击鼠标可以陷入,ctrl+ alt + 2可以释放鼠标

(qemu)gdbservertcp::1234 [若使用了-s参数则无需此步]


然后在gdb的提示符下输入: target remote localhost:1234 连接gdb stub

然后开始设置断点,比如: break start_kernel

然后输入c命令,然后qemu继续运行后,就会在start_kernel 入口处停了下来。

这时候你就可以输入各种gdb命令来对linux kernel进行hack了。。

当然,这里采用gdb的一个前端工具ddd会更好。但还是需要学习一些常用的gdb命令(这样才能更熟练的进行调试)


常用的gdb调试命令:

1. file <文件名> :  加载被调试的可执行程序文件.

2. run(简写r也可以): 运行被调试程序,直到遇到断点.

3. c : 继续执行被调试程序,直到下一断点.

4. b : 设置断点.

5. d <编号> : 删除断点.

6. info breakpoints : 显示已设置的断点列表.

7. s : 源码级的单步进入.

8. n : 源码级的单步步过.

9. si/ni : 指令级的单步进入和步过.(需要先运行display /i $pc)

10. info all-register: 显示所有寄存器的值.

11. p /x $eax : 以16进制显示某一特定寄存器的值.

12. q: 退出gdb调试环境.

13. disassemble <0xXXXXXXXX> : 反汇编指定地址处的指令.(加/r选项,显示对应汇编代码的机器码)

14. set disassembly-flavor <intel | att> : 设定汇编显示的格式(Intel格式或者AT&T格式)

15. 修改指定地址的内存数据:set {unsigned char} <0xXXXXXXXX>= <new data>

16. 显示源代码文件: list

17. info stack: 查看栈追踪(栈回溯). 或者使用 backtrace 也可以

18. x /nfu <addr> : 查看指定地址处的内存内容.

n: 表示个数.   f(format): x,16进制.  d,10进制.   u(每一项的长度): b,单字节. w,4字节. h,双字节.

例如: x /1xw 0x804a010