GBD调试QEMU启动问题

4 篇文章 0 订阅

1. 目标

核心目标为解决特定硬件及特定内核版本下QEMU启动问题。
前段时间我们通过“在aarch64环境下编译kvmtool,基于kvmtool启动最小linux”来验证aarch64架构下虚拟化支持问题,发现在一环境下,出现CPU stuck问题,直接导致裸机卡住,详细信息如下:
在这里插入图片描述我们需要进一步定位问题所在,故产生了通过GDB去调试启动过程,由于kvmtool调试手段有限,下面我们采用qemu来完成该项任务。

2. qemu编译

2.1 下载qemu

通过网址https://download.qemu.org/进行相应版本选择下载,我们选择比较新的版本,6.0.0进行下载

wget https://download.qemu.org/qemu-6.0.0.tar.bz2
tar -xvf qemu-6.0.0.tar.bz2
cd qemu-6.0.0/

2.2 依赖下载

软件依赖包可以通过网站https://pkgs.org/搜索下载

wget https://vault.centos.org/centos/8/PowerTools/aarch64/os/Packages/re2c-0.14.3-2.el8.aarch64.rpm
wget https://vault.centos.org/centos/8/PowerTools/aarch64/os/Packages/ninja-build-1.8.2-1.el8.aarch64.rpm
rpm -ivh re2c-0.14.3-2.el8.aarch64.rpm
rpm -ivh ninja-build-1.8.2-1.el8.aarch64.rpm

2.3 编译

添加kvm和debug选项,仅编译需要的aarch64架构的以节约编译时间,如下所示:

mkdir build && cd build
../configure --enable-kvm  --target-list=aarch64-softmmu --enable-debug
make -j64

3. 内核及文件系统编译制作

在配置菜单中,启用内核debug,关闭地址随机化,不然断点处无法停止

-> Kernel hacking
    -> [*] Kernel debugging
    
-> Kernel hacking
    -> Compile-time checks and compiler options
       ->  [*] Compile the kernel with debug info
       ->  [*] Provide GDB scripts for kernel debugging
        
-> Kernel Features
  -> [ ] Randomize the address of the kernel image

内核及文件系统编译制作具体可以参考https://blog.csdn.net/nanhai_happy/article/details/124835581

4. 调试

4.1 GDB知识回顾

GDB 全称“GNU symbolic debugger”,主要功能就是监控程序的执行流程。
常用调试命令如下:

调试命令作用
target remote <hostname>:<port>连接到主机名:端口
target remote :<port>如果没有指定主机名,GDB将使用localhost
break (b) <location>在源代码指定的某一行设置断点
hbreak <location>在源代码指定的某一行设置硬件断点
info break输出GDB会话中所有断点的信息
enable <breakpoint-number>启用断点号断点
disable <breakpoint-number>禁用断点号断点
delete(d) <breakpoint-number>以断点号删除断点。
info registers打印出CPU的寄存器
run (r)执行被调试的程序,其会自动在第一个断点处暂停执行
run (r)执行被调试的程序,其会自动在第一个断点处暂停执行
continue (c)当程序在某一断点处停止后,用该指令可以继续执行,直至遇到断点或者程序结束
next (n)令程序一行代码一行代码的执行
step(s)如果有调用函数,进入调用的函数内部;否则,和 next 命令的功能一样
print (p)<var>打印指定变量的值
set <var>=<val>将val值赋给变量var
list (l)显示源程序代码的内容,包括各行代码所在的行号
finish(fi)结束当前正在执行的函数,并在跳出函数后暂停程序的执行
return(return)结束当前调用函数并返回指定值,到上一层函数调用处停止程序执行
jump(j)使程序从当前要执行的代码处,直接跳转到指定位置处继续执行后续的代码
quit (q)终止调试

4.2 qemu启动调试虚拟机

启动路径如下:

./qemu-system-aarch64 -enable-kvm -machine virt -cpu host -smp 4 -m size=8192M  -kernel ../../linux-4.19.90/arch/arm64/boot/Image -initrd ../../busybox-1.35.0/rootfs.cpio -append "nokaslr root=/dev/ram rdinit=/linuxrc " -L ../pc-bios/ -nographic -S -s

可以通过组合键CTRL+A松开后按X或者进入系统后poweroff退出qemu

参数说明:

-kernel ../../linux-4.19.90/arch/arm64/boot/Image : 指定启用的内核镜像;
-initrd ../../busybox-1.35.0/rootfs.cpio:指定启动的内存文件系统;
-append "nokaslr root=/dev/ram rdinit=/linuxrc ": 附加参数,其中 nokaslr 参数必须添加进来,防止内核起始地址随机化;
-s :监听在 gdb 1234 端口,若不想使用1234端口,则可以使用-gdb tcp:<port>来取代-s选项 
-S :表示启动后就挂起,等待 gdb 连接;
-nographic:不启动图形界面,调试信息输出到终端与参数 console=ttyAMA0 组合使用;
-L ../pc-bios/ :指定启动bios

4.3 GDB调试

cd linux-4.19.90/
gdb
(gdb) file vmlinux
(gdb) target remote :1234
(gdb) hbreak start_kernel
(gdb) hbreak rest_init
(gdb) info break
(gdb) c
(gdb) info registers

根据需要设置不同的的断点,进行单步调试
如下图:
在这里插入图片描述详细调试过程这里不做赘述,网上有很多更详细的GDB资料可供参考,请谅解

5. 问题记录

  • 编译qemu(git clone)报无法克隆子模组路径
    具体报错信息如下:
git clone https://github.com/qemu/qemu.git
git checkout stable-6.0
../configure --enable-kvm  --target-list=aarch64-softmmu
正克隆到 '/nvme0n1/qemu/capstone'...
fatal: 无法访问 'https://gitlab.com/qemu-project/capstone.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/capstone.git' 到子模组路径 '/nvme0n1/qemu/capstone'
克隆 'capstone' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/dtc'...
fatal: 无法访问 'https://gitlab.com/qemu-project/dtc.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/dtc.git' 到子模组路径 '/nvme0n1/qemu/dtc'
克隆 'dtc' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/meson'...
fatal: 无法访问 'https://gitlab.com/qemu-project/meson.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/meson.git' 到子模组路径 '/nvme0n1/qemu/meson'
克隆 'meson' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/slirp'...
fatal: 无法访问 'https://gitlab.com/qemu-project/libslirp.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/libslirp.git' 到子模组路径 '/nvme0n1/qemu/slirp'
克隆 'slirp' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/tests/fp/berkeley-softfloat-3'...
fatal: 无法访问 'https://gitlab.com/qemu-project/berkeley-softfloat-3.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/berkeley-softfloat-3.git' 到子模组路径 '/nvme0n1/qemu/tests/fp/berkeley-softfloat-3'
克隆 'tests/fp/berkeley-softfloat-3' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/tests/fp/berkeley-testfloat-3'...
fatal: 无法访问 'https://gitlab.com/qemu-project/berkeley-testfloat-3.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/berkeley-testfloat-3.git' 到子模组路径 '/nvme0n1/qemu/tests/fp/berkeley-testfloat-3'
克隆 'tests/fp/berkeley-testfloat-3' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/ui/keycodemapdb'...
fatal: 无法访问 'https://gitlab.com/qemu-project/keycodemapdb.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/keycodemapdb.git' 到子模组路径 '/nvme0n1/qemu/ui/keycodemapdb'
克隆 'ui/keycodemapdb' 失败。按计划重试
正克隆到 '/nvme0n1/qemu/capstone'...
fatal: 无法访问 'https://gitlab.com/qemu-project/capstone.git/':Could not resolve host: gitlab.com
fatal: 无法克隆 'https://gitlab.com/qemu-project/capstone.git' 到子模组路径 '/nvme0n1/qemu/capstone'
第二次尝试克隆 'capstone' 失败,退出
/nvme0n1/qemu/scripts/git-submodule.sh: failed to update modules

Unable to automatically checkout GIT submodules ' ui/keycodemapdb tests/fp/berkeley-testfloat-3 tests/fp/berkeley-softfloat-3 meson dtc capstone slirp'.
If you require use of an alternative GIT binary (for example to
enable use of a transparent proxy), then please specify it by
running configure by with the '--with-git' argument. e.g.

 $ ./configure --with-git='tsocks git'

Alternatively you may disable automatic GIT submodule checkout
with:

 $ ./configure --with-git-submodules=validate

and then manually update submodules prior to running make, with:

 $ scripts/git-submodule.sh update  ui/keycodemapdb tests/fp/berkeley-testfloat-3 tests/fp/berkeley-softfloat-3 meson dtc capstone slirp

通过git clone下载下来的qemu不包含子模块,需要连网下载,由于我这边是离线环境,故会报上述错误,直接通过去https://download.qemu.org/网站下载相应的压缩包即可解决

  • 设置断点后,继续执行报Cannot access memory at address 0xffff000009000990错误
    详细过程如下:
(gdb) b start_kernel
Breakpoint 1 at 0xffff000009000990: file init/main.c, line 531.
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0xffff000009000990

Command aborted.
(gdb) q

经过查阅资料,需要附加参数(-append “nokaslr root=/dev/ram rdinit=/linuxrc”),其中 nokaslr 参数必须添加进来且为第一个参数,防止内核起始地址随机化,导致 gdb 断点不能命中;及第一次只能用hbreak (GDB的硬件断点) 替代普通断点。

  • qemu编译是报错 ERROR: Cannot find Ninja
    解决方法为下载相关依赖包,进行安装,网址为https://pkgs.org/
  • qemu-system-aarch64启动虚拟机报错为failed to find romfile “efi-virtio.rom”
    解决方法启动参数加入-L …/pc-bios/,该目录在qemu源码目录中

6. 参考文献

https://docs.kernel.org/dev-tools/gdb-kernel-debugging.html
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821624963/Debugging+Guest+Applications+with+QEMU+and+GDB
https://www.ebpf.top/post/qemu_gdb_busybox_debug_kernel/
https://blog.csdn.net/qq_28351609/article/details/114855630
https://www.songbingjia.com/nginx/show-60573.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值