linux工具---用qemu调试linux内核
2016-06-13 15:33
621 查看
一.qemu模拟x86
1.1 qemu的安装
ubuntu 12.04下安装qemu很简单,
sudo apt-get install qemu
1.2 linux内核的编译
www.kernel.org 下载内核, 以linux-3.0.1为例
sun@ubuntu:/work/x86/kernel$ tar xf ./linux-3.0.1.tar.bz2
sun@ubuntu:/work/x86/kernel$ cd linux-3.0.1/
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make menuconfig
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make bzImage
这样就会生成内核文件 arch/x86/boot/bzImage
1.3 busybox的编译
http://www.busybox.net/ 下载busybox, 以busybox-1.21.1.tar.bz2为例
sun@ubuntu:/work/x86/kernel$ tar xv busybox-1.21.1.tar.bz2
sun@ubuntu:/work/x86/kernel$ cd busybox-1.21.1/
sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make menuconfig
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs) //静态方式编译
Networking Utilities --->
[ ] inetd //去掉inetd
sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make install
这会生成 _install目录
1.4 最小文件系统的建立
只用一个脚本creatfs.sh就可以生成cramfs文件系统
#!/bin/sh
KERNEL=$(pwd)
BUSYBOX=$(find busybox* -maxdepth
0)
LINUX=$(find linux* -maxdepth
0)
#create filesystem
cd $BUSYBOX
mkdir -pv proc sys dev etc etc/init.d //先创建系统目录
cat << EOF > etc/init.d/rcS //生成rcS文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
EOF
chmod 777 ./etc/init.d/rcS //修改rcS权限
cd -
#create cpio img
cd $BUSYBOX/_install
find . | cpio -o --format=newc > $KERNEL/rootfs.img
cd -
#create zip img
cd $KERNEL
gzip -c rootfs.img > rootfs.img.gz
1.5 启动qemu
#!/bin/sh
LINUX=$(find linux* -maxdepth
0)
#启动qemu
if [ $# = 0 ] ; then
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd
rootfs.img.gz -append "root=/dev/ram
rdinit=sbin/init noapic"
fi
if [ "$1" = "s" ] ; then
qemu-system-i386 -s -S -kernel
$LINUX/arch/i386/boot/bzImage -initrd
rootfs.img.gz -append "root=/dev/ram
rdinit=sbin/init noapic"
fi
如果没有参数直接运行qemu,
如果有参数s, 则进入调试模式
qemu参数:
-s : 在1234接受gdb调试连接
-S : 虚拟机启动后立即暂停,等侍gdb连接
最后所有文件如下:
sun@ubuntu:/work/x86/kernel$ tree -L 1
.
├── busybox-1.21.1 //busbyox及_install
├── creatfs.sh //文件系统生成脚本
├── linux-3.0.1 //Linux源码,及
bzImage
└── start.sh //启动qemu
注意:
a. 将linux启动信息打印到串口
在qemu启动时加上:
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init noapic console=ttyS0" -serial
file:/tmp/serial.out
就会在/tmp/serial.out中出现系统的信息
b. 将linux启动信息直接打印到控制台
加入 -nographic 和stdio,则会在当前运行的terminal中把linux启动信息打印出来
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init console=ttyS0" -nographic
c. qemu的快捷键
C-a h print this help
C-a x exit emulator
C-a s save disk data back to file (if -snapshot)
C-a t toggle console timestamps
C-a b send break (magic sysrq)
C-a c switch between console and monitor
C-a C-a sends C-a
二.qemu模拟ARM
2.1 qemu-system-arm的安装
如果只是apt-get install qemu,不会安装qemu-system-arm
sun@ubuntu:/work/qemu$ sudo apt-get install qemu qemu-system qemu-utils
sun@ubuntu:/work/qemu$ qemu-system-arm --version
QEMU emulator version 1.0.50 (Debian 1.0.50-2012.03-0ubuntu2.1), Copyright (c) 2003-2008 Fabrice Bellard
注意: 编译工具链可以不用apt-get install 来安装,试过6410自带的交叉编译工具链是完全可用的。
2.2 编译u-boot, kernel, busybox
这儿的编译跟x86的不同之处是:
不论是编译u-boot 还是 linux-3.0.1 还是busybox都需要个改Makefile中的ARCH与CROSS_COMPILE两个变量c
ARCH ?= arm
CROSS_COMPILE ?= /opt/6410/4.3.2/bin/arm-none-linux-gnueabi-
编译u-boot时是用的make ca9x4_ct_vxp_config
编译Linux-3.0.1时是用的 arch/arm/configs/vexpress_defconfig
内核编译命令: make vexpress_defconfig && make -j16
a.copy zImage
在arch/arm/Makefile中
278 zImage Image xipImage bootpImage uImage: vmlinux
279 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
280 echo "$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@"
281 cp $(boot)/$@ ../
其中$(boot)/$@是zImage的路径
../ 是linux-3.01源码的上一层
2.3 用ext3系统启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
#!/bin/sh
KERNEL=$(pwd)
BUSYBOX=$(find busybox* -maxdepth
0)
LINUX=$(find linux* -maxdepth
0)
#create filesystem
cd $BUSYBOX
mkdir -pv proc sys dev etc etc/init.d //先创建系统目录
cat << EOF > etc/init.d/rcS //生成rcS文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
EOF
chmod 777 ./etc/init.d/rcS //修改rcS权限
cd -
用ext3.sh脚本创建ext3文件系统
#!/bin/sh
#创建一个32M的空文件
dd if=/dev/zero
of=a9rootfs.ext3 bs=1M count=32
#格式化为EXT3
sudo mkfs.ext3 a9rootfs.ext3
# 挂载到a9rootdir目录
mkdir -pv /tmp/a9rootdir
sudo mount -t ext3 a9rootfs.ext3 /tmp/a9rootdir/ -o loop
#拷贝文件到该目录,相对于放到a9rootfs.ext3里面
sudo cp /work/qemu/rootfs/* /tmp/a9rootdir/ -Rf
sudo umount /tmp/a9rootdir
启动:
qemu-system-arm -kernel
zImage -M vexpress-a9 -append "root=/dev/mmcblk0
console=ttyAMA0 console=tty0" -sd a9rootfs.ext3 -serial stdio
2.4 用NFS启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
启动:
qemu-system-arm -m
256 -kernel zImage -serial stdio -M vexpress-a9 -append
root="/dev/nfs console=ttyAMA0 console=tty0 nfsroot=10.0.0.1:/work/qemu/rootfs rw ip=10.0.0.2:10.0.0.1:10.0.0.1:255.255.255.0 " -net
nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=qemu-ifup &
qemu-ifup脚本如下:
#!/bin/sh
echo "Executing /etc/qemu-ifup"
sudo ifconfig $1 10.0.0.1
前提是主机上的nfs-server己配置好
三. qemu调试linux系统
3.1 启动调试模式下的qemu
sun@ubuntu:/work/x86/kernel$ sh start.sh s
3.2 另起一个terminal
sun@ubuntu:/work/x86/kernel/linux-3.0.1$
gdb vmlinux
Reading symbols from /work/x86/kernel/linux-3.0.1/vmlinux...done.
(gdb) target
remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb) b kernel_init
Breakpoint 1 at 0xc15c7786: file init/main.c, line
781.
(gdb) c
Continuing.
Breakpoint 1, kernel_init (unused=0x0) at
init/main.c:781
781 {
(gdb) l
776 panic("No init found. Try passing init= option to kernel. "
777 "See Linux Documentation/init.txt for guidance.");
778 }
779
780 static int __init kernel_init(void * unused)
781 {
782 /*
783 * Wait until kthreadd is all set-up.
784 */
785 wait_for_completion(&kthreadd_done);
(gdb)
3.3 每次都这么操作比较麻烦,可以建立一个gdbinit脚本
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi .gdbinit
target remote localhost:1234
b kernel_init
c
然后下次运行时就可以
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ gdb vmlinux
注意,如果用gdbinit脚本时出现以下问题:
warning: File "/work/x86/kernel/linux-3.0.1/.gdbinit" auto-loading
has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /work/x86/kernel/linux-3.0.1/.gdbinit
line to your configuration file "/home/sun/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/sun/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run
from the shell:
info "(gdb)Auto-loading safe path"
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi ~/.gdbinit
set auto-load safe-path /
在~/.gdbini中加入上面这一行,取消掉
[参]:
以QEMU模拟Linux,学习linux内核
http://www.cnblogs.com/senix/archive/2013/02/21/2921221.html
使用qemu调试linux内核
http://blog.csdn.net/aero_boy/article/details/6262609
使用qemu模拟Coretex-A9运行u-boot和Linux
http://www.linuxidc.com/Linux/2012-07/65478.htm
1.1 qemu的安装
ubuntu 12.04下安装qemu很简单,
sudo apt-get install qemu
1.2 linux内核的编译
www.kernel.org 下载内核, 以linux-3.0.1为例
sun@ubuntu:/work/x86/kernel$ tar xf ./linux-3.0.1.tar.bz2
sun@ubuntu:/work/x86/kernel$ cd linux-3.0.1/
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make menuconfig
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make bzImage
这样就会生成内核文件 arch/x86/boot/bzImage
1.3 busybox的编译
http://www.busybox.net/ 下载busybox, 以busybox-1.21.1.tar.bz2为例
sun@ubuntu:/work/x86/kernel$ tar xv busybox-1.21.1.tar.bz2
sun@ubuntu:/work/x86/kernel$ cd busybox-1.21.1/
sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make menuconfig
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs) //静态方式编译
Networking Utilities --->
[ ] inetd //去掉inetd
sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make install
这会生成 _install目录
1.4 最小文件系统的建立
只用一个脚本creatfs.sh就可以生成cramfs文件系统
#!/bin/sh
KERNEL=$(pwd)
BUSYBOX=$(find busybox* -maxdepth
0)
LINUX=$(find linux* -maxdepth
0)
#create filesystem
cd $BUSYBOX
mkdir -pv proc sys dev etc etc/init.d //先创建系统目录
cat << EOF > etc/init.d/rcS //生成rcS文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
EOF
chmod 777 ./etc/init.d/rcS //修改rcS权限
cd -
#create cpio img
cd $BUSYBOX/_install
find . | cpio -o --format=newc > $KERNEL/rootfs.img
cd -
#create zip img
cd $KERNEL
gzip -c rootfs.img > rootfs.img.gz
1.5 启动qemu
#!/bin/sh
LINUX=$(find linux* -maxdepth
0)
#启动qemu
if [ $# = 0 ] ; then
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd
rootfs.img.gz -append "root=/dev/ram
rdinit=sbin/init noapic"
fi
if [ "$1" = "s" ] ; then
qemu-system-i386 -s -S -kernel
$LINUX/arch/i386/boot/bzImage -initrd
rootfs.img.gz -append "root=/dev/ram
rdinit=sbin/init noapic"
fi
如果没有参数直接运行qemu,
如果有参数s, 则进入调试模式
qemu参数:
-s : 在1234接受gdb调试连接
-S : 虚拟机启动后立即暂停,等侍gdb连接
最后所有文件如下:
sun@ubuntu:/work/x86/kernel$ tree -L 1
.
├── busybox-1.21.1 //busbyox及_install
├── creatfs.sh //文件系统生成脚本
├── linux-3.0.1 //Linux源码,及
bzImage
└── start.sh //启动qemu
注意:
a. 将linux启动信息打印到串口
在qemu启动时加上:
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init noapic console=ttyS0" -serial
file:/tmp/serial.out
就会在/tmp/serial.out中出现系统的信息
b. 将linux启动信息直接打印到控制台
加入 -nographic 和stdio,则会在当前运行的terminal中把linux启动信息打印出来
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init console=ttyS0" -nographic
c. qemu的快捷键
C-a h print this help
C-a x exit emulator
C-a s save disk data back to file (if -snapshot)
C-a t toggle console timestamps
C-a b send break (magic sysrq)
C-a c switch between console and monitor
C-a C-a sends C-a
二.qemu模拟ARM
2.1 qemu-system-arm的安装
如果只是apt-get install qemu,不会安装qemu-system-arm
sun@ubuntu:/work/qemu$ sudo apt-get install qemu qemu-system qemu-utils
sun@ubuntu:/work/qemu$ qemu-system-arm --version
QEMU emulator version 1.0.50 (Debian 1.0.50-2012.03-0ubuntu2.1), Copyright (c) 2003-2008 Fabrice Bellard
注意: 编译工具链可以不用apt-get install 来安装,试过6410自带的交叉编译工具链是完全可用的。
2.2 编译u-boot, kernel, busybox
这儿的编译跟x86的不同之处是:
不论是编译u-boot 还是 linux-3.0.1 还是busybox都需要个改Makefile中的ARCH与CROSS_COMPILE两个变量c
ARCH ?= arm
CROSS_COMPILE ?= /opt/6410/4.3.2/bin/arm-none-linux-gnueabi-
编译u-boot时是用的make ca9x4_ct_vxp_config
编译Linux-3.0.1时是用的 arch/arm/configs/vexpress_defconfig
内核编译命令: make vexpress_defconfig && make -j16
a.copy zImage
在arch/arm/Makefile中
278 zImage Image xipImage bootpImage uImage: vmlinux
279 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
280 echo "$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@"
281 cp $(boot)/$@ ../
其中$(boot)/$@是zImage的路径
../ 是linux-3.01源码的上一层
2.3 用ext3系统启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
#!/bin/sh
KERNEL=$(pwd)
BUSYBOX=$(find busybox* -maxdepth
0)
LINUX=$(find linux* -maxdepth
0)
#create filesystem
cd $BUSYBOX
mkdir -pv proc sys dev etc etc/init.d //先创建系统目录
cat << EOF > etc/init.d/rcS //生成rcS文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
EOF
chmod 777 ./etc/init.d/rcS //修改rcS权限
cd -
用ext3.sh脚本创建ext3文件系统
#!/bin/sh
#创建一个32M的空文件
dd if=/dev/zero
of=a9rootfs.ext3 bs=1M count=32
#格式化为EXT3
sudo mkfs.ext3 a9rootfs.ext3
# 挂载到a9rootdir目录
mkdir -pv /tmp/a9rootdir
sudo mount -t ext3 a9rootfs.ext3 /tmp/a9rootdir/ -o loop
#拷贝文件到该目录,相对于放到a9rootfs.ext3里面
sudo cp /work/qemu/rootfs/* /tmp/a9rootdir/ -Rf
sudo umount /tmp/a9rootdir
启动:
qemu-system-arm -kernel
zImage -M vexpress-a9 -append "root=/dev/mmcblk0
console=ttyAMA0 console=tty0" -sd a9rootfs.ext3 -serial stdio
2.4 用NFS启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
启动:
qemu-system-arm -m
256 -kernel zImage -serial stdio -M vexpress-a9 -append
root="/dev/nfs console=ttyAMA0 console=tty0 nfsroot=10.0.0.1:/work/qemu/rootfs rw ip=10.0.0.2:10.0.0.1:10.0.0.1:255.255.255.0 " -net
nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=qemu-ifup &
qemu-ifup脚本如下:
#!/bin/sh
echo "Executing /etc/qemu-ifup"
sudo ifconfig $1 10.0.0.1
前提是主机上的nfs-server己配置好
三. qemu调试linux系统
3.1 启动调试模式下的qemu
sun@ubuntu:/work/x86/kernel$ sh start.sh s
3.2 另起一个terminal
sun@ubuntu:/work/x86/kernel/linux-3.0.1$
gdb vmlinux
Reading symbols from /work/x86/kernel/linux-3.0.1/vmlinux...done.
(gdb) target
remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb) b kernel_init
Breakpoint 1 at 0xc15c7786: file init/main.c, line
781.
(gdb) c
Continuing.
Breakpoint 1, kernel_init (unused=0x0) at
init/main.c:781
781 {
(gdb) l
776 panic("No init found. Try passing init= option to kernel. "
777 "See Linux Documentation/init.txt for guidance.");
778 }
779
780 static int __init kernel_init(void * unused)
781 {
782 /*
783 * Wait until kthreadd is all set-up.
784 */
785 wait_for_completion(&kthreadd_done);
(gdb)
3.3 每次都这么操作比较麻烦,可以建立一个gdbinit脚本
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi .gdbinit
target remote localhost:1234
b kernel_init
c
然后下次运行时就可以
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ gdb vmlinux
注意,如果用gdbinit脚本时出现以下问题:
warning: File "/work/x86/kernel/linux-3.0.1/.gdbinit" auto-loading
has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /work/x86/kernel/linux-3.0.1/.gdbinit
line to your configuration file "/home/sun/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/sun/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run
from the shell:
info "(gdb)Auto-loading safe path"
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi ~/.gdbinit
set auto-load safe-path /
在~/.gdbini中加入上面这一行,取消掉
[参]:
以QEMU模拟Linux,学习linux内核
http://www.cnblogs.com/senix/archive/2013/02/21/2921221.html
使用qemu调试linux内核
http://blog.csdn.net/aero_boy/article/details/6262609
使用qemu模拟Coretex-A9运行u-boot和Linux
http://www.linuxidc.com/Linux/2012-07/65478.htm
相关文章推荐
- Linux基础
- Linux源代码目录
- linux内存管理
- Linux初学 - head,tail,grep,sed,yum,find
- laravel5.0在linux环境下解决.htaccess无效和去除index.php
- Linux学习笔记(2)
- Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)
- Linux-SVN 常用命令详解
- centos gitlab安装
- Linux学习笔记(1)
- Linux下GitLab的快速安装以及备份
- go1.6.2 linux/amd64 的一个bug: gcc: 无法识别的选项‘-no-pie’
- linux 的重定向
- linux 查看静态库,动态库是32位还是64位
- Linux fd_set结构用法
- Linux-systemctl命令
- CentOS环境下使用javaCV
- CentOS正确关机方法(转)
- linux中 epoll
- 【linux】linux创建用户并授予sudo权限