通过qemu调试centos7内核
Posted rayylee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过qemu调试centos7内核相关的知识,希望对你有一定的参考价值。
1.安装依赖
sed -e 's|^mirrorlist=|#mirrorlist=|g' \\
-e 's|^#baseurl=http://mirror.centos.org|baseurl=https://mirrors.tuna.tsinghua.edu.cn|g' \\
-i.bak \\
/etc/yum.repos.d/CentOS-*.repo
yum install -y vim wget lrzsz
yum install -y gcc bc gcc-c++ ncurses ncurses-devel cmake elfutils-libelf-devel openssl-devel libgcrypt-devel glibc-static
yum install -y qemu-kvm gdb net-tools texinfo
systemctl stop firewalld
systemctl mask firewalld
setenforce 0
sed ‐i '/^SELINUX/s/=.*/=disabled/' /etc/selinux/config
2.下载内核版本解压并进入解压目录
wget https://vault.centos.org/7.9.2009/os/Source/SPackages/kernel-3.10.0-1160.el7.src.rpm
3.清理内核源目录
make mrproper
4.使用make menuconfig菜单来订制内核功能
make menuconfig
(
配置ext4、virtio为 Y
修改Makefile: -O2改为-O1; 删掉-Werror
)
5.编译内核
make vmlinux -j 4
make bzImage
6. 制作initramfs
下载busybox
wget https://busybox.net/downloads/busybox-1.28.0.tar.bz2
cd busybox-1.28.0
配置编译选项busybox,开启Build static binary (no shared libs)
选项
make menuconfig
(
Settings --->
--- Build Options
[*] Build static binary (no shared libs)
)
编译busybox
make -j 4
make install // 编译安装文件在_install目录下
制作initramfs
mkdir initramfs
cd initramfs
cp ../_install/* -rf ./
mkdir dev,proc,sys
cp -a /dev/null,console,tty,tty1,tty2,tty3,tty4 dev/
rm linuxrc
vim init
(
#!/bin/busybox sh
mount –t proc none /proc
mount –t sysfs none /sys
exec /sbin/init
)
chmod a+x init
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
7. 通过qemu-kvm调试内核
/usr/libexec/qemu-kvm -kernel arch/x86/boot/bzImage -initrd initramfs.cpio.gz -s -S -append nokaslr -vnc :0
-kernel bzImage
:指定内核路径
-initrd file
:指定initramdisk路径
-s
:-gdb tcp::1234
的缩写, 开启一个gdbserver, 可以通过TCP端口1234连接
-S
: 启动后立即暂停
-append nokaslr
: 指定内核参数nokaslr
, 禁止内核地址随机化, 否则gdb打断点找不到地址
-vnc :0
: 开启vnc监听0端口
PS:
--monitor stdio
开启qmp交互
打开另一个终端
gdb vmlinux
或者
gdb vmlinux --tui
(gdb) target remote:1234
Remote debugging using :1234
0x0000000000000000 in irq_stack_union ()
(gdb) hb start_kernel // 设置硬件断点
Hardware assisted breakpoint 1 at 0xffffffff81d9ae44: file init/main.c, line 489.
(gdb) info b
Num Type Disp Enb Address What
1 hw breakpoint keep y 0xffffffff81d9ae44 in start_kernel at init/main.c:489
breakpoint already hit 1 time
(gdb) c
Continuing.
Breakpoint 1, start_kernel () at init/main.c:489
489
小技巧: gdb可以直接添加command
gdb vmlinux -ex="target remote:1234" -ex="hb start_kernel"
8. 遇到的问题
8.1 gdb vmlinux会出现 “Remote ‘g’ packet reply is too long”错误
Remote 'g' packet reply is too long: 0000000000000000d981ffffffff00000004000000000000001006000000000000040000000000000010060000000000903fc081ffffffff883fc081ffffffff0000000000000000130000000000000000000000000000000cc5130300000000ffffffff00000000200000000000000020a1d981ffffffff8e0000000000000044aed981ffffffff8200000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
解决办法: 修改gdb源码, 重新编译
wget ftp://sourceware.org/pub/gdb/releases/gdb-7.6.tar.gz
tar -xvf gdb-7.6.tar.gz
cd gdb-7.6
注释掉:
if (buf_len > 2 * rsa->sizeof_g_packet)
error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf);
并在后面添加:
if (buf_len > 2 * rsa->sizeof_g_packet)
rsa->sizeof_g_packet = buf_len;
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
if (rsa->regs[i].pnum == -1)
continue;
if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
rsa->regs[i].in_g_packet = 0;
else
rsa->regs[i].in_g_packet = 1;
重新编译
mkdir -p /opt/gdb_7_6
./configure --prefix=/opt/gdb_7_6
make && make install
echo "PATH=\\$PATH:/opt/gdb_7_6/bin" >> /root/.bashrc
参考
以上是关于通过qemu调试centos7内核的主要内容,如果未能解决你的问题,请参考以下文章