Qemu + gdbでXen上のOSカーネルを見る
とりあえず、gdb上でどうやってユーザモードのバイナリを見るかというタッチの話。Xenにとって、上に載せるOSがアプリケーションに相当することに注意する。
サマリ
ちょっとした準備(XenのDOM0としてx86_32のmini-osを起動する)
今のところ、x86_64なqemuのgdbスタブは正常でない。というわけで、Xenとmini-osの両方をx86_32でビルドする必要がある。
メモリマップの関係で、32bit環境ではmini-osをそのままDOM0として使うことは出来ない(もちろん、DOM0のための機能がmini-osには無いので、この修正をしてもmini-osはカーネルを開始することが出来ない)。
平たく言えば、ロードアドレスを0から0xc0000000に変更する。
.ascii ",VIRT_BASE=0xc0000000" /* &_text from minios_x86_32.lds */ .ascii ",ELF_PADDR_OFFSET=0xc0000000"
SECTIONS { . = 0xc0000000;
あとは、普通に両者をビルドする。
(トップで、) make XEN_TARGET_ARCH=x86_32 xen (extras/mini-osで、) make XEN_TARGET_ARCH=x86_32
stubを有効にしたqemuの起動
微妙に重要なのは-Sオプションで、これを指定すると、エミュレーションはpause状態から開始される。よってgdb側から実行開始を指示することが出来る。
qemu-system-x86_64 -cpu qemu32 -gdb tcp::1234 --kernel xen-3.4.2 -initrd ../../../extras/mini-os/mini-os -append "noreboot console=com1" -serial stdio -S -nographics
qemuはMultibootのローダを持っているのでそれを利用する。Dom0のイメージは何故かinitrdオプションで指定する。xenを普通にビルドするとgzipで圧縮してしまうので、予め圧縮を解除しておくのが好ましい。
あとは、普通にgdbを起動する。デバッグ対象としては、ユーザモードのプログラムを指定する。もし、OSが独自のバイナリフォーマットを採用していたり、事前にstripしているなら、それに変換する前のELFやPEのイメージを利用する。
oku@sandbox ~ $ gdb check/xen-3.4.2/extras/mini-os/mini-os GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu"... (gdb) target remote localhost:1234 Remote debugging using localhost:1234 [New Thread 1] 0x0000fff0 in ?? () (gdb) b start_kernel Breakpoint 1 at 0xc000e08b: file kernel.c, line 482. (gdb) c Continuing. Breakpoint 1, start_kernel (si=Cannot access memory at address 0x8 ) at kernel.c:482 482 { (gdb)
起動後は、target remote localhost:1234でqemuに接続→ブレークポイントを設定→cで実行開始 のようにする。
もちろん、InsightとかDDDのようなgdbフロントエンドでも同様に作業を行える。
同様の手法でxenにブレークポイントを置くことも出来るが、そのためにはxen-sym-3.4.2をgdbにロードする必要がある。gdbはMultibootバイナリをロードすることは出来ない。