初心者のためのkgdbによるカーネルデバッグ環境構築めも

Windows 7 RC(x64)をホストとしてVMware Workstation 6.5.2 で2台のUbuntu 9.04(x64)を作成し、一台をデバッグする側、もう一台をデバッグされる側とする。

OSの基本的な準備

両方の仮想マシンで実施する。


Ubuntu 9.04(x64)のセットアップイメージを適当なサイトからダウンロードする。
次にVMwareでハードウェアを設定する。Linuxカーネル巨大なため、デバッグされる側のハードディスクは15GB以上が必須。デバッグする側は5GBもあればOK。また、Windows 7(RC)がホストの場合、ネットワークをブリッジ接続(物理ネットワーク接続の状態を復元する:任意)にしないと仮想マシンがネットワークに接続できないことに注意。
OSをインストールして、初回起動を完了するとUpdate Managerが更新をリストしてくるので、とりあえず全部当てる。この構成ではVMware Toolsは既にインストールが完了しているので、追加の作業はない。


ついでに使いやすいように日本語に対応させる。Systemメニュー > Administration > Language Support > Install / Remove LanguagesからJapaneseをインストールし、表示を日本語に切り替える。
その後、ログアウト・ログインし、システムメニュー > 設定 > キーボード > レイアウトタブ > 日本語106キーボードを選択し、レイアウトを日本に変更して、システム全体に適用。これで日本語表示、日本語入力が可能になる。

ハードウェアの設定

両方の仮想マシンにシリアルポートを名前付きパイプで追加。
デバッグする側は「\\.\pipe\com_1」などとし、「この端末はクライアントです」「接続先は仮想マシンです」「ポーリングでCPUを破棄する:No」。
デバッグされる側は「\\.\pipe\com_1」などと(両方で同じに)し、「この端末はサーバーです」「接続先はアプリケーションです」「ポーリングでCPUを破棄する:No」。

カーネルソースの展開

両方の仮想マシンで実施する。デバッグする側はソースを表示するため、デバッグされる側はコンパイルを行うため。

$ sudo apt-get install kernel-package libncurses-dev ncurses-dev libqt3-mt-dev
$ sudo apt-get install linux-source
$ cd /usr/src/
$ sudo tar xfv linux-source-2.6.28.tar.bz2

カーネルコンパイル

デバッグされる側のみ実施する。

$ cd /usr/src/linux-source-2.6.28
$ sudo make menuconfig
(中略)
Kernel hacking --> (中略)
                   [*] Compile the kernel with debug info  
                   (中略)
                   -*- Compile the kernel with frame pointers
                   (中略)
                   [*] KGDB: kernel debugging with remote gdb 
(中略)
$ sudo vi Makefile
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 28
EXTRAVERSION = .9-kgdb
NAME = Erotic Pickled Herring
(中略)
$ sudo make-kpkg --initrd kernel_image
  1. make menuconfigで上記3つのコンパイルオプションを指定(この例の環境ではデフォルトで指定済みでした)。
  2. MakefileのEXTRAVERSIONに独自バージョンであることを示すコメントを追記(内容は任意)。
  3. make-kpkgでカーネルとinitrdを生成する。

コンパイルにはとても長い時間がかかります(1時間以上)。コンパイルが完了すると、このディレクトリに vmlinux が生成されます。

新しいカーネルのインストールと起動

デバッグされる側のみ。

$ cd /usr/src/
$ sudo dpkg -i linux-image-2.6.28.9-kgdb_2.6.28.9-kgdb-10.00.Custom_amd64.deb 
$ sudo vi /boot/grub/menu.lst
(中略)
## ## End Default Options ##

title           Ubuntu 9.04, kernel 2.6.28.9-kgdb
uuid            2b4e47e7-a8a9-49a9-97bd-571b170b4c6d
kernel          /boot/vmlinuz-2.6.28.9-kgdb root=(略) noprompt quiet splash kgdboc=ttyS0,115200 kgdbwait
initrd          /boot/initrd.img-2.6.28.9-kgdb
quiet

title           Ubuntu 9.04, kernel 2.6.28.9-kgdb (recovery mode)
(中略)
  1. dpkgでカーネルをインストールする。
  2. インストールすると menu.lst に追加されているので、追加されたエントリーの kernel 行に kgdboc=ttyS0,115200 kgdbwait を追記する。

次にコンパイルしてできたvmlinuxをデバッグする側にコピーする。コピー先はどこでもいい。
最後にデバッグされる側を再起動すると、起動中に以下のメッセージを表示して停止する。

kgdb: Waiting for connection from remote gdb...

デバッガで接続

デバッグする側のみ。


カレントディレクトリに先ほどコンパイルしたvmlinuxがあるものとする。

$ ls
Desktop  Documents  Music  Pictures  Public  Templates  Videos  examples.desktop  vmlinux
$ gdb 
(gdb) file vmlinux 
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
kgdb_register_io_module (new_kgdb_io_ops=0x0) at kernel/kgdb.c:1721
1721		wmb(); /* Sync point after breakpoint */
(gdb) c
Continuing.

gdbを起動し、カーネルのシンボルを読み込み、シリアルポートに接続すると、デバッグされる側に接続される。kernel/kgdb.cの1721行目でブレークしていることが分かる。
ここからは果てしなく続くGNU文化との戦いになるが、とりあえず c|continue コマンドを使うとブレークから再開することだけ書いておく。

参考