Linux Kernelのビルドとデバッグ
概要
ここでは、QEMUを用いてLinux Kernelを実行し、gdbによってLinux Kernelをデバッグする方法についてまとめます。
Kernelを最低限動かすことを目指しています。
環境
ここの手順は以下の環境を前提とする。
- OS: "Ubuntu 20.04.4 LTS"
- GCC: 9.4.0
- QEMU: 4.2.1
- GDB: 9.2
必要ソフトウェアのビルド
QEMU上で実行するためには、kernelの他に初期RAMディスクが必要です。
ここでは、busyboxを利用した手順について記します。
Linux Kernelのビルド
流れとしては以下に示すようになる。
- Kernelのソース入手
-
.config
の生成 - ビルド
Kernel のソース入手
kernel.org からtarなりをwget
してください。
git でも良いですが、時間かかるのでtarがおすすめです。
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.207.tar.xz
tar -xf linux-5.2.207.tar.xz
.config
の生成
.configはホストマシンの/boot/config-5.15.0-41-generic
をコピーするとかありますが、
ここでは最小限な.configの生成を目指します。
cd linux-x.x.x
make allnoconfig
make menuconfig
ここでなんかエラー言われたら多分 ncurses-dev
がないあたりが考えられます(エラー読んでね)
なので、以下で解決するはずです。
sudo apt install libncurses-dev
Kernel DebugのためにKGDB周辺の機能を有効にします。
ざっと以下のあたりでしょうか。
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_KDB=y
CONFIG_KALLSYMS_ALL=y
CONFIG_DEBUG_INFO=y
あとはビルドするだけです。
make -j `nproc`
成功すると直下に vmlinux
ができているはずです。
BusyBoxのビルドとinitrdの生成
Busyboxを用いてinitrdを作成します。
ちゃんとしたLinuxのシステムはinitrdから/dev/sdaあたりを本ちゃんのRootfsとして利用しますが、ここではKernelが使えればいいので、initrdを用いたLinux Kernelの起動に留めます。
BusyBoxのビルド
https://busybox.net からソースを持ってきます。
cd busybox-x.x.x
make defconfig
make menuconfig
BusyBoxの.configで CONFIG_STATIC=y
にしておきます。
あとはビルドするだけです。
make -j `nproc`
initrdのイメージ作成
まず、busyboxをビルドした成果物を吐き出します。
これには以下のmakeコマンドで実行することで、Busyboxのソースディレクトリ直下に_install
というディレクトリが作成されます。
make install
そしてそこに移動し、以下のコマンド群を実行し最低限+アルファの環境に仕上げていきます。
cd _install
mkdir -p etc/init.d proc sys
次にetc/init.d/rcS
ファイルを作成し、procfsとsysfsをマウントするようにします。
# Result of rcS
cat etc/init.d/rcS
mount -t devtmpfs devtempfs /dev
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
そして、このファイルに実行権限を与えます。
chmod +x etc/init.d/rcS
これらの用意をしたものをcpioを用いてinitrdにします。
cd _install
find . | cpio -o --format=newc > ../rootfs.img
QEMU + GDBでデバッグする
ここまででできたものらを以下のようにQEMUで実行します。
qemu-system-x86_64 -S -s -kernel linux-5.4.207/arch/x86_64/boot/bzImage -initrd busybox-1.35.0/rootfs.img -append "root=/dev/ram rdinit=/sbin/init nokaslr console=ttyS0" -nographic
GDB側を用意します。
gdb linux-5.4.207/vmlinux
(gdb) target remote :1234
あとはGDBでいい感じに遊ぶことができます。
参考文献
- https://kaki-no-tane.hatenablog.com/entry/2018/12/03/135302
- https://proc-cpuinfo.fixstars.com/2017/07/test-and-debug-linux-kernel-with-qemu/
- https://sites.google.com/site/kandamotohiro/linux/kgdb
- https://qiita.com/Brutus/items/3ca1237efdf1711a6428
- https://shuntavista.jimdofree.com/2019/12/05/linux-kernel-をbuildしてqemuで動かす/
- https://nullpo-head.hateblo.jp/entry/2015/04/20/172059
- https://balau82.wordpress.com/2010/03/27/busybox-for-arm-on-qemu/
- https://leavatail.hatenablog.com/entry/2020/12/12/150000
- https://qiita.com/kaishuu0123/items/33621af2aca44d8d2c72
ちなみに
ここの手順は、ftraceの仕組みの軽い調査のために用意した環境のメモです。