gdb调试Qemu ARM64仿真平台上的Linux Kernel

prtos, info 嵌入式虚拟化技术评论1字数 4302阅读14分20秒阅读模式
  1. 建立Qemu aarch64仿真开发环境

主机平台:Ubuntu 20.04.2 LTS

工作目录:

export WORK_DIR=/home/tom/hdd/linux-qemu/repos

1.1 安装qemu-system-aarch64

sudo apt-get install qemu-system-aarch64

Note: 也可以下载qemu源码自行编译安装,具体请参考[1]的2.2节.

1.2 通过buidroot搭建initramfs cpio文件系统

我们使用buildroot软件包[3]来制作rootfs文件系统映像,下载buildroot软件包,并进入配置界面:

wget https://buildroot.org/downloads/buildroot-2021.08.tar.bz2
tar xvf buildroot-2021.02.4.tar.bz2
cd buildroot-2021.02.4
make menuconfig

1.2.1 配置模板ARM64目标平台

Target options->AArch64(little endian)

Target options-> Target Architecture Variant (cortex-A57

示意图如下:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

1.2.2 配置交叉编译器

Toolchain->Toolchain type 选择“External toolchain”:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

Toolchain->Toolchain选择"Arm AArch64 2020.11”:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

Note: 选择Linaro AArch64 2018.05版本也是可以的。

1.2.3 配置登录用户名和密码

System configuration-> Enable root login with password, 并且设置root密码,这里设置为"adsf”:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

1.2.4 配置Linux 控制台

System configuration-> Run a getty (login prompt) after boot->TTY port设置为"ttyAMA0"。

gdb调试Qemu ARM64仿真平台上的Linux Kernel

 

1.2.5 配置目标平台常用工具包

Target packages->选择Show packages that are also provided by busybox:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

Target packages-> Debugging, profiling and benchmark可以选择自己感兴趣的工具,这里选择strace:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

1.2.4 配置文件系统格式

Filesystem images选择cpio the root filesystem (for use as an initial RAM filesystem):

gdb调试Qemu ARM64仿真平台上的Linux Kernel

1.2.5 编译buildroot文件系统

cd $WORK_DIR/buildroot-2021.08
make

buildroot-2021.08/output/images目录下会生成两个系统映像:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

1.3编译ARM64平台的Linux Kernel

安装交叉工具链

sudo apt install gcc-aarch64-linux-gnu

 

下载Linux内核,并生成默认的配置文件:

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.14.6.tar.xz
tar xvf linux-5.14.6.tar.xz
cd linux-5.14.6
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig

在产生的linux-5.14.6/.config文件中修改以下三个选项:

CONFIG_CMDLINE="console=ttyAMA0"
CONFIG_INITRAMFS_SOURCE="/home/tom/hdd/linux-qemu/repos/buildroot-2021.08/output/images/rootfs.cpio"
CONFIG_DEBUG_INFO=y

编译kernel:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4

在编译的过程中会出现需要用户配置选项的交互输入,则一路默认回车键,直到出现交互输入Built-in initramfs compression mode时,因为我们编译initramfs文件系统时,没有选择压缩模式,所以这里选择8:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

继续回车,直到遇到Kernel command line type交互输入时,选择1:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

其余一路回车直到配置结束.

然后再次运行编译命令:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4

生成vmlinux,Image,Image.gz示意图如下:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

Note: Linux原始镜像为vmlinux,后续可能是Image、Image.gz、uImage镜像, 处理过程是

  • 通过link-vmlinux.sh生成vmlinux和map文件。
  • 通过objcopy移除vmlinux中不必要段,输出binary格式Image。
  • 对Image进行压缩,输出不同格式的压缩文件,比如gzip对应的gz。
  • 对gz加上uboot头信息,生成uImage文件。

ARM64平台则仅支持Image.gz和Image

1.4启动 Qemu Linux系统

qemu-system-aarch64 \
-machine virt \
-cpu cortex-a57 \
-machine type=virt \
-nographic -smp 1 \
-m 2048 \
-kernel ./arch/arm64/boot/Image \
--append "console=ttyAMA0"

 

示意图如下:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

 

2.调试ARM64平台的Linux Kernel

2.1 在主机和Qemu ARM64平台虚拟机间共享文件

在buildroot-2021.08/.config文件中更新选项:

BR2_ROOTFS_OVERLAY="/home/tom/hdd/linux-qemu/repos/buildroot-files"

然后再次编译buildroot和Linux kernel

cd $WORK_DIR/buildroot-2021.08/
make
cd $WORK_DIR/linux-5.14.6
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4

 

启动Linux Kernel后,我们就可以看到拷贝的文件:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

2.2 调试ptrace()系统调用的示例

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, const char *argv[]) {
  int pid;

  if ((pid = fork() == 0)) {
    // The child process does a PTRACE_TRACEME,
    // While being traced, the tracee will stop each time a signal is delivered,
    // even if the signal is being ignored.
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    execl("/bin/ls", "ls", "-l", NULL);
  } else {
    // block parent process until any of its children has finished.
    wait(NULL);
    // to tell child process to run until the next system call (enter or exit)
    // until the child process exits.
    ptrace(PTRACE_SYSCALL, pid, 0, 0);
    ptrace(PTRACE_CONT, pid, NULL, NULL);
  }

  return 0;
}

 

编译示例代码(因为我们运行的目标平台是ARM64,所以这里必须使用交叉编译器):

cd $WORK_DIR/buildroot-files
aarch64-linux-gnu-gcc simple_trace.c -o simple_trace

示意图如下:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

2.3调试内核并截获ptrace系统调用

启动Qemu Linux并冻结CPU等待gdb调试运行.

cd $WORK_DIR/ linux-5.14.6
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a57 \
-machine type=virt \
-nographic -smp 1 \
-m 2048 \
-kernel ./arch/arm64/boot/Image \
--append "console=ttyAMA0" \
-s -S

-S:冻结CPU等待gdb的continue命令

-s: 是"-gdb tcp::1234"的简写,意思是通过本机的1234端口接听gdb命令

打开另外一个终端,输入命令

cd $WORK_DIR/ linux-5.14.6
gdb-multiarch ./vmlinux

备注:

如果gdb-multiarch没安装的化,使用命令

sudo apt-get intall gdb-multiarch

安装gdb-multiarch。

在gdb 命令窗口输入:

set architecture aarch64
target remote localhost:1234
continue

 

gdb调试Qemu ARM64仿真平台上的Linux Kernel

这样qemu上的Linux会收到gdb输入的continue命令,继续运行,我们在Linux 终端输入命令:

cat /proc/kallsyms |grep sys_ptrace
cat /proc/kallsyms |grep sys_ptrace

获取系统调用服务例程sys_ptrace()的入口地址,这里是0xffff80001008fea8:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

在gdb命令中,我们在地址0xffff80001008fea8设置断点,然后在Linux中运行我们的示例:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

就会在gdb中截获这个断点,这样我们可以用gdb命令调试指定的例程,比如这里的sys_ptrace。示意图如下:

gdb调试Qemu ARM64仿真平台上的Linux Kernel

大伙在搭建的过程中,如果遇到问题,欢迎留言或者mail to cwsun@prtos.org

 

参考文献

[1]http://www.prtos.org/xen_on_arm64_and_qemu/

[2]https://www.cnblogs.com/arnoldlu/p/14102272.html

[3]https://buildroot.org/

 

 

继续阅读
prtos, info
  • 本文由 发表于 2021年9月25日 15:58:02
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
  • qemu
  • arm64
  • linux
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定