一、准备环境
1.安装编译工具链
sudo apt-get install gcc-aarch64-linux-gnu
sudo apt-get install libncurses5-dev build-essential git bison flex libssl-dev
2.制作根文件系统
//编译busybox
wget https://busybox.net/downloads/busybox-1.33.1.tar.bz2
tar -xjf busybox-1.33.1.tar.bz2
cd busybox-1.33.1
//打开静态库编译选项
make menuconfig
Settings --->
[*] Build static binary (no shared libs) ;
//指定编译工具
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
//编译
make
make install
3.编译内核
根据arch/arm64/configs/defconfig 文件生成.config
make defconfig ARCH=arm64
执行编译
make ARCH=arm64 Image -j8 CROSS_COMPILE=aarch64-linux-gnu-
4.启动qemu
apt-get install build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libboost-all-dev autoconf libtool libssl-dev libpixman-1-dev libpython-dev python-pip python-capstone virtualenv
wget https://download.qemu.org/qemu-4.2.1.tar.xz
tar xvJf qemu-4.2.1.tar.xz
cd qemu-4.2.1
./configure --target-list=x86_64-softmmu,x86_64-linux-user,arm-softmmu,arm-linux-user,aarch64-softmmu,aarch64-linux-user --enable-kvm
make
sudo make install
5.启动linux内核
/usr/local/bin/qemu-system-aarch64 -m 512M -smp 4 -cpu cortex-a57 -machine virt -kernel arch/arm64/boot/Image -append "rdinit=/linuxrc nokaslr console=ttyAMA0 loglevel=8" -nographic -s
二、触发系统调用
把test.c进行交叉编译
aarch64-linux-gnu-gcc -o test test.c -static
将生成的test文件移到root目录下,然后重新编译
make ARCH=arm64 Image -j8 CROSS_COMPILE=aarch64-linux-gnu-
进行调试:添加断点、启动调试、执行test程序
三、分析time/gettimeofday 系统调用的执行过程
在 ARM64 架构中,当用户态程序发起系统调用时,CPU 会自动从用户态切换到内核态,并触发一个同步异常,即系统调用异常。此时 CPU 会跳转到内核中预定义的异常处理函数 el0_sync。在 el0_sync 函数中,第一步是保存异常发生时的程序执行现场,包括程序计数器 PC(ELR_EL1)和程序状态寄存器 PSTATE(SPSR_EL1)。接下来根据异常的类型跳转到对应的处理函数,即 el0_svc。在 el0_svc 函数中,会调用 el0_svc_handler 和 el0_svc_common 函数,并将系统调用号传递给 invoke_syscall 函数。invoke_syscall 函数将通用寄存器中的内容传入 syscall_fn(),引出系统调用内核处理函数 __arm64_sys_gettimeofday。处理完系统调用后,内核需要恢复程序执行现场,包括 ELR_EL1 和 SPSR_EL1 寄存器的值,最后通过 eret 指令返回到用户态继续执行用户程序。整个过程由 ret_to_user 函数中的 kernel_exit 0 完成。