本文记录了在ubuntu20.04上,使用QEMU搭建arm64 的Linux开发调试环境。可以方便得使用gdb调试内核,既可以作为学习linux kernel源码的实验环境,也可以用于ARM64内核驱动开发调试环境。
版本和环境信息如下:
平台:ubuntu20.04
kernel版本:linux 5.10
qemu版本:5.2.0
qemu模拟环境:ARM64
gcc version :10.2.0
交叉编译工具链:aarch64-linux-gnu-
QEMU是一套由法布里斯·贝拉(Fabrice Bellard)所编写的以GPL许可证分发源码的模拟处理器,在GNU/Linux平台上使用广泛。本文搭建的是gdbserver+主机gdb远程调试的环境,这里QEMU仿真器就扮演了gdbserver角色。这里选择用QEMU模拟ARM cortex-a53平台,可以使用参数"-machine help"查看QEMU支持哪些CPU,使用参数"-device help"查看支持哪些device。
安装QEMU,有两种方式,源码安装和命令行安装:
sudo wget https://download.qemu.org/qemu-5.2.0.tar.xz
tar xvJf qemu-5.2.0.tar.xz
cd qemu-5.2.0
./configure
make && make install
ubuntu上需要安装的依赖,可参考《QEMU编译指南》一文。
如果只需要安装一种平台的QEMU,可以通过configure配置如下:
./configure –target-list=aarch64-softmmu
ubuntu20.04源提供相对比较高的QEMU版本,可以选择命令行直接安装。对于比较老旧的发行版,建议选择源码安装。
apt-get install qemu qemu-system qemu-user
安装完成后,可以通过Tab键补全检查安装好的qemu 工具:"qemu-system-"
root@ubuntu20_04:# qemu-
qemu-img qemu-system-cris qemu-system-mips64 qemu-system-ppc64le qemu-system-tricore
qemu-io qemu-system-hppa qemu-system-mips64el qemu-system-riscv32 qemu-system-unicore32
qemu-make-debian-root qemu-system-i386 qemu-system-mipsel qemu-system-riscv64 qemu-system-x86_64
qemu-nbd qemu-system-lm32 qemu-system-moxie qemu-system-s390x qemu-system-xtensa
qemu-pr-helper qemu-system-m68k qemu-system-nios2 qemu-system-sh4 qemu-system-xtensaeb
qemu-system-aarch64 qemu-system-microblaze qemu-system-or1k qemu-system-sh4eb
qemu-system-alpha qemu-system-microblazeel qemu-system-ppc qemu-system-sparc
qemu-system-arm qemu-system-mips qemu-system-ppc64 qemu-system-sparc64
qemu-system-aarch64就是我们要使用的,用于模拟ARM64平台的qemu工具。
可以通过命令"apt-cache search aarch64" 查看系统源中有哪些安装包可供安装:
... ...
gcc-9-aarch64-linux-gnu-base - GCC, the GNU Compiler Collection (base package)
gcc-aarch64-linux-gnu - GNU C compiler for the arm64 architecture
qemu-efi-aarch64 - UEFI firmware for 64-bit ARM virtual machines
qemu-system-arm - QEMU full system emulation binaries (arm)
cpp-10-aarch64-linux-gnu - GNU C preprocessor
cpp-8-aarch64-linux-gnu - GNU C preprocessor
g++-10-aarch64-linux-gnu - GNU C++ compiler (cross compiler for arm64 architecture)
g++-8-aarch64-linux-gnu - GNU C++ compiler (cross compiler for arm64 architecture)
gcc-10-aarch64-linux-gnu - GNU C compiler (cross compiler for arm64 architecture)
gcc-10-aarch64-linux-gnu-base - GCC, the GNU Compiler Collection (base package)
gcc-10-plugin-dev-aarch64-linux-gnu - Files for GNU GCC plugin development.
gcc-8-aarch64-linux-gnu - GNU C compiler (cross compiler for arm64 architecture)
... ...
笔者选择"gcc-10-aarch64-linux-gnu"进行安装:
sudo apt-get install gcc-10-aarch64-linux-gnu
# 为方便使用可以软连接或者重命名aarch64-linux-gnu-gcc-10
mv /usr/bin/aarch64-linux-gnu-gcc-10 /usr/bin/aarch64-linux-gnu-gcc
笔者使用的是linux 5.10源码,大家可以按照需求下载具体的内核源码。配置编译过程如下:
export ARCH=arm64
export CROSS_COPILE=aarch64-linux-gnu-
make defconfig
#如果需要可以在此 配置initramfs路径为"/tmp/rootfs/xxx"
# 记得勾选上"Compile the kernel with debug info",以及其他自己调试需要的配置选项
make menuconfig
make -j8 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
在arch/arm64/boot/ 下检查生成的内核,其中"Image"为非压缩版,"Image.gz"为压缩内核,并包含了自解压程序。
可以根据自己需要制定rootfs,可以选择ramdisk、initramfs等格式,这里不再赘述。笔者是为了学习调试内核启动过程,因此使用"menu"制作一个极简的rootfs镜像:
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
# 修改Makefile,去掉"find init hello ***"和"qemu -kernel ../linux"语句
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
rootfs.img就是接下来要使用的根文件系统镜像。
启动测试QEMU环境,通过gdb remote功能,链接QEMU并调试内核。有一点需要注意,由于我们调试的是ARM64模拟环境,需要使用"gdb-multiarch"而不是ubuntu自带的gdb工具,如果系统没有可以通过下面命令安装:
sudo apt-get install gdb-multiarch
QEMU工具参数众多,本文只使用必备的几个基础参数,读者可以根据自己的需求和环境情况组合参数。示例如下:
# 在一个窗口输入启动
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 2 -m 4096M -kernel /tmp/arch/arm64/boot/Image.gz -nographic -append "console=ttyAMA0 init=/linuxrc ignore_loglevel" -initrd /tmp/rootfs/rootfs.img -S -gdb tcp::9000
关于qemu-system-aarch64的几个参数解释如下:
-smp 核数目
-m 物理内存大小
-kernel 内核压缩镜像位置
-initrd rootfs位置
-nographic 不使用图形界面,不加可能会因为无法启动图形界面而失败
-append cmdline启动参数
-S 在入口处阻塞CPU
-gdb tcp::xxxx 指定通信通道为 本地tcp通道(因为是在同一个机器上),端口号为xxxx,如果不需要指定端口号可以用-s 代替
# 新开一个窗口启动gdb并链接
gdb-multiarch /tmp/linux5.10/vmlinux
(gdb)target remote :9000
(gdb)break start_kernel
(gdb)continue
(gdb)step
在"target remote :9000"成功后,即可使用gdb对另一端的内核进行单步调试。下面粘贴下实际操作的结果图:
图1 gdb 链接启动的本地QEMU
本文在ubuntu20.04上搭建了调试ARM64平台的QEMU环境,可以方便得使用gdb调试内核,是内核开发调试中一种经典的工具组合。不同的发行版可能存在细微差异,总体流程是一样的,hope it works for you ~