在看此文章之前,请先参考《利用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文档:]
-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