QEMU调试Linux系统的USB协议栈
通过使用QEMU调试Linux系统的USB协议栈来学习USB协议栈。
mingdu.zheng at gmail dot com
安装QEMU
sudo apt-get install qemu-system-i386
启动QEMU进入调试模式
qemu-system-i386 -kernel vmlinuz-2.6.32 -initrd initrd.img -append console=ttyS0 -nographic -S -s -monitor tcp::3333,server,nowait -device pci-ohci
-kernel vmlinuz-2.6.32:指定内核文件
-initrd initrd.img:指定引导时使用的RAM Disk,RAM Disk中集成了BusyBox,包含一些基础命令
-append console=ttyS:传递给内核的参数,将内核控制台输出重定向到串口
-nographic:无图形窗口模式,纯文本模式,不需要窗口
-S:启动虚拟机时不执行代码,当受到GDB指令时才执行
-s:为-gdb tcp::1234的缩写形式,打开GDB Server,监听端口为1234
-monitor tcp::3333,server,nowait:将monitor重定向到TCP流,创建TCP服务器,监听端口为3333
-device pci-ohci:添加OHCI主机控制器到虚拟机
连接QEMU Monitor
socat tcp:localhost:3333 stdio
在另一个终端,使用socat将qemu monitor的输出重定向到当前终端的标准输入输出。
打开GDB连接到QEMU
gdb vmlinux-2.6.32 -ex "dir linux-2.6.32" -ex "target remote :1234" -ex "b usb_init" -ex "b ohci_hcd_mod_init" -ex "b ehci_hcd_init" -ex "b usb_stor_init" -ex "b storage_probe" -ex "c"
-ex “dir /home/firm/linux/linux-2.6.32/”:GDB启动后执行dir命令,指定源代码查找路径
-ex “target remote :1234”:接着执行target命令,连接到QEMU的GDB Server
-ex “b usb_init”:接着执行b命令,设置断点,usb_init为USB核心层的初始化入口函数
-ex “b ohci_hcd_mod_init”:继续设置断点,ohci_hcd_mod_init为OHCI主机控制器的初始化入口函数
-ex “b ehci_hcd_init”:继续设置断点,ehci_hcd_init为EHCI主机控制器的初始化入口函数
-ex “b usb_stor_init”:继续设置断点,usb_stor_init为Mass Storage类设备驱动的初始化入口函数
-ex “b storage_probe”:继续设置断点,storage_probe为Mass Storage类设备驱动的探测函数
-ex “c”:执行c命令,虚拟机开始启动
断点应按需设置
创建磁盘映像文件
dd if=/dev/zero of=usbdisk.img bs=512 count=102400
mkfs.ext2 usbdisk.img
通过QEMU Monitor插入优盘
(qemu) drive_add 0 id=my_usb_disk,if=none,file=usbdisk.img
OK
(qemu) device_add usb-storage,id=my_usb_disk,drive=my_usb_disk
drive_add创建一个虚拟的磁盘驱动器,usbdisk.img为磁盘映像文件
device_add添加优盘设备到虚拟机,使用上一步创建的磁盘驱动器
通过QEMU Monitor移除优盘
(qemu) device_del my_usb_disk