前一段时间在写一个linux的文件系统,需要调试linux内核,勉强搭了一个调试环境,所以强答一下~
我用的是linux主机(Cent OS)+gdb + 虚拟机(vmware上的ubuntu 14.04),通过虚拟机的串口进行通信,能够单步调试内核源码。原理应该和楼上qemu+gdb的方法类似。由于内核源码默认是开启了优化的,所以很多代码可能被优化掉了,没法进行单步调试。但是自己写的代码是完全可以单步调试的。下面说一下具体步骤。
0.准备工作
在主机(linux)上安装虚拟机,虚拟机上安装ubuntu。这个就不详细说了……
1.给虚拟机添加串口(虚拟机在关机状态下)
Vmware->settings->hardware->add->serial
port->output to socket->socket(named pipe): /tmp/isocket from:server to: an application √connect at power on->√ yield CPU
其中/tmp/isocket是一个文件,主机和虚拟机利用这个文件进行串口通信。
测试:
socat和telnet建立连接,主机通过/tmp/isocket收发数据,虚拟机通过/dev/ttyS1收发数据(ttyS1是默认的串口)
主机需要两个程序socat和telnet
在主机terminal里:
$ socat /tmp/isocket tcp-listen:9001 &
$ telnet 127.0.0.1 9001
在虚拟机上:
#chmod 777 /dev/ttyS1
#cat /dev/ttyS1
此时主机terminal里输入信息虚拟机可以通过ttyS1接收到。
#echo ‘hello’ > /dev/ttyS1
主机的terminal可以收到
telnet输入Ctrl+]结束
如果串口收发没有问题,可以继续。
2.编译linux内核
gdb调试需要vmlinux文件,有两种方法
①提取内核
Extract-vmlinux是一个bash脚本,可以把现有系统的vmlinux提取出来
(复制一下,chmod改成可执行文件)
# ./extract-vmlinux /boot/vmlinuz-xxxx-generic > vmlinux
②完全重新编译(推荐)
在虚拟机里下载内核源码、解压、进入源码目录
make menuconfig
make //可以加-jn选项多线程编译,但在我这里貌似并没有什么卵用。
make bzImage
make modules
make modules_install
make install
reboot
重启之后uname -a可以查看内核信息
然后,把编译好的内核文件夹拷贝到主机相同目录下(可能只拷贝vmlinux文件就足够)
3.gdb调试
首先在虚拟机的/boot/grub/grub.cfg中,在默认启动项后增加kgdboc=ttyS1,115200 kgdbwait 两个参数
改完之后,重启虚拟机,虚拟机会停在
等待
然后在主机terminal中
$ socat /tmp/isocket tcp-listen:9001 &
$ cd
$ gdb vmlinux
(gdb) target remote:9001
成功的话,是这个样子
到这里就成功了,已经可以进行调试了
gdb的命令next continue、break等等都可以用了。
在这里输入c就会把控制权交还给虚拟机,当我们想把控制权交还给主机的gdb是,在虚拟机的terminal中输入echo g>/proc/sysrq-trigger
在你想调试的内核代码函数的地方加上断点(break func),当虚拟机运行到的时候,就会在主机的gdb上停下了,前提是想调试的代码没有在编译时被编译器优化。内核默认-O2优化,并不知道怎么-O0优化。