利用qemu-system-aarch64調試Linux內核(arm64)

qemu-system-aarch64調試linux-4.12內核

藉助Linux操作系統中已有的工具,比如mkinitramfs構建rootfs

前提條件
(0) arm64物理服務器或虛擬機
(1) qemu-2.11.1: qemu-system-aarch64
(2) busybox-1.31.1
(3) 內核版本爲linux-4.12

安裝qemu

由於qemu的編譯過程中存在-CFLAGS=-O2-g將不允許debug信息的出現,因此需要在./configure的時候添加–enable-debug(或–enable-debug --enable-debug-info)選項.爲方便以後調試Qemu源碼,本次安裝將開啓debug模式,即在配置選項中增加–enable-debug和–enable-debug-info選項

# ./configure --target-list=aarch64-softmmu, aarch64-linux-user --enable-debug --enable-debug-info

安裝busybox

BusyBox配置選項:

# make menuconfig

並有如下設置:
Busybox Settings —>
— Build Options
[*] Build BusyBox as a position independent executable
編譯安裝

# make -j$(nproc)
# make install -j$(nproc)

製作根文件系統

1. 利用Linux操作系統提供的工具mkinitramfs

# mkinitramfs -o initramdisk

產生製作完成的根文件系統initramdisk,但該文件相對來說還是大了些,接下來將使用自制initramfs的方式創建根文件系統initramfs。

2. 利用busybox製作根文件系統
前提是已經安裝了busybox

# cat gen_initramfs.sh
#!/bin/bash
ROOTFS=rootfs
BUSYBOX=$(find busybox* -maxdepth 0 -type d)
SYSROOT=$(gcc --print-sysroot)
GLIBC_VERSION=$(ldd --version | head -1 | cut -d' ' -f5)
DYNAMIC_LIB_PATH_64=/lib/aarch64-linux-gnu

rm -rf $ROOTFS
mkdir -p ${ROOTFS}/{proc,sys,dev,etc,etc/init.d,lib,lib64,mnt,tmp,go}

cat > $ROOTFS/etc/init.d/rcS <<EOF
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
ifconfig lo up
EOF

chmod +x $ROOTFS/etc/init.d/rcS

cat > $ROOTFS/etc/inittab <<EOF
# /etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
EOF

chmod +x $ROOTFS/etc/inittab

cp -rP ${BUSYBOX}/_install/* ${ROOTFS}

cp -rP ${DYNAMIC_LIB_PATH_64}/libc-${GLIBC_VERSION}.so ${ROOTFS}/lib64/
cp -rP ${DYNAMIC_LIB_PATH_64}/libc.so.6 ${ROOTFS}/lib64/

cp -rP ${DYNAMIC_LIB_PATH_64}/libm-${GLIBC_VERSION}.so ${ROOTFS}/lib64/
cp -rP ${DYNAMIC_LIB_PATH_64}/libm.so.6 ${ROOTFS}/lib64/

cp -rP ${DYNAMIC_LIB_PATH_64}/librt-${GLIBC_VERSION}.so ${ROOTFS}/lib64/
cp -rP ${DYNAMIC_LIB_PATH_64}/librt.so.1 ${ROOTFS}/lib64/

cp -rP ${DYNAMIC_LIB_PATH_64}/libpthread-${GLIBC_VERSION}.so ${ROOTFS}/lib64/
cp -rP ${DYNAMIC_LIB_PATH_64}/libpthread.so.0 ${ROOTFS}/lib64/

cp -rP ${DYNAMIC_LIB_PATH_64}/ld-${GLIBC_VERSION}.so ${ROOTFS}/lib64/
cp -rP ${DYNAMIC_LIB_PATH_64}/ld-linux-x86-64.so.1 ${ROOTFS}/lib64/

cd ${ROOTFS}
ln -sf linuxrc init
find . | cpio -o --format=newc > ../initramfs

編譯Linux內核

# make menuconfig
# make –j$(nproc)

需要重點關注兩個文件:vmlinuxImage,分別位於
(1) linux-4.12/vmlinux
(2) linux-4.12/arch/arm64/boot/Image

調試Linux內核

以根文件系統方式啓動

# qemu-system-aarch64 -smp 4 -M virt -cpu cortex-a57 -nographic -m 2048M -kernel linux-4.12/arch/arm64/boot/Image -append "console=ttyAMA0" -initrd initramdisk

調試內核
1. 默認添加gdbserver tcp::1234,命令之後添加參數選項 ‘-s’

# qemu-system-aarch64 -nographic  -m 2048M -smp 4 -M virt -cpu host -enable-kvm -kernel linux-4.12/arch/arm64/boot/Image -initrd initramfs -append "console=ttyAMA0 init=/linuxrc rw" -s
# gdb -tui linux-4.12/vmlinux

該方式採用參數選項“-s”,默認添加“gdbserver tcp::1234”的方式,相當於在執行命令時已經啓動了gdbserver和監聽端口1234,在使用gdb 調試vmlinux時,只需要在gdb中輸入"target remote :1234",即可啓動調試。

2. 額外添加gdbserver tcp::1234, 命令行之後添加參數選項 ‘-S’

# qemu-system-aarch64 -nographic  -m 2048M -smp 4 -M virt -cpu host -enable-kvm -kernel linux-4.12/arch/arm64/boot/Image -initrd initramfs -append "console=ttyAMA0 init=/linuxrc rw" -S

需要執行兩步:
(1) 執行該命令後,需要按組合鍵“Ctrl + A + C”切換到Monitor模式,並輸入gdbserver tcp::1234,然後按Enter鍵,出現“Waiting for gdb connection on device ‘tcp::1234’”;
(2) 另開一個terminal,在該處執行如下命令

# gdb -tui linux-4.12/vmlinux

然後在加載完內核調試文件後,輸入"target remote :1234",對應(1)中設置的端口1234。
兩步驟設置完成後,接下來就可以根據需要調試代碼。
在這裏插入圖片描述

參考鏈接

感謝相關作者!!!
Linux aarch64 編譯 & qemu 搭建實驗平臺.
Linux內存管理之—環境搭建(在QEMU上運行Linux 5.4.0)
ramdisk文件系統製作和移植

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章