はじめに
xv6は、MITのOperating System Engineeringのクラスで使われている教材で、UNIX V6 をx86ベースに作りなおされたシンプルなOSです。
xv6自体の解説書籍はありませんが、UNIX V6ならLions本やはじめてのOSコードリーディングが有名なので、
多少の差異があるものの、書籍片手にソースリーディングができます。
ただ、読むだけでは実際にどう動くかのイメージがなかなか掴めないので、ステップ実行できる環境を作ってみます。
以下の環境を前提に記述します。
- Ubuntu 14.04
- GCC 4.8.4
- GNU gdb 7.7.1
- QEMU 2.0.0
xv6のソース入手
Gitでリポジトリをクローンします。
git clone git://github.com/mit-pdos/xv6-public.git
コンパイル
make 一発でOK
Makefileを読むと、CFLAGS にGDBでデバッグ情報を付加するオプション(-g)、
コンパイルの最適化を行わないオプション(-O0)が最初からついているので、デバッグ用の追加設定は不要です。
cd xv6-public
make
kernelという実行ファイルが生成されていればOKです。
QEMUで実行
make qemu-nox-gdb
*** Now run 'gdb'.
qemu-system-i386 -nographic -hdb fs.img xv6.img -smp 2 -m 512 -S -gdb tcp::26000
qemu-gdb だとQEMUのコンソールが出現しますが、qemu-nox-gdb だと現在のコンソールでQEMUが起動します。
-Sオプションが付いているので起動直後に停止中となり、デバッガの接続待ちとなります。
別のコンソールを立ち上げ、GDBでTCPの26000番ポートに繋ぎに行きます。
cd xv6-public
gdb kernel
(gdb) target remote localhost:26000
Remote debugging using localhost:26000
0x0000fff0 in ?? ()
ソースコードをアタッチします。カレントディレクトリがソースのルートなので、パスは .(ドット)でOKです。
(gdb) source .
.: 成功です.
(単純に"gdb"で起動した場合は、ここでシンボルファイルの指定を行います)
(gdb) symbol-file kernel
main関数にブレークポイントを設定します。
(gdb) b main
Breakpoint 1 at 0x801036ff: file main.c, line 19.
表示を切り替えて、ブレークポイントまで進めます。
(gdb) la src
(gdb) c
Continuing.
設定したブレークポイントで止まった状態になりました。
ここで nコマンドを入力すると次の1行に移ります。
F5キーで直前のコマンドを繰り返すので、F5を押すたびカーソルが移っていきます。
これでソースリーディングが段違いにはかどりますね。
注意点
ターゲットのアーキテクチャが異なると、正しくデバッグ出来ないことがあります。
今回xv6はi386で動作することを前提にビルド・起動しているので、GDBでもこれに合わせた設定が必要です。
手元の環境では次のようになっていました。
(gdb) show arch
The target architecture is set automatically (currently i386)
もし異なるアーキテクチャが示されていたら、次のようなファイルを作れば初期設定ができます。
set arch i386
もしくは、同じ内容をGDB起動後に手入力してもOKです。