初心者のための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
- make menuconfigで上記3つのコンパイルオプションを指定(この例の環境ではデフォルトで指定済みでした)。
- MakefileのEXTRAVERSIONに独自バージョンであることを示すコメントを追記(内容は任意)。
- 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) (中略)
- dpkgでカーネルをインストールする。
- インストールすると 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 コマンドを使うとブレークから再開することだけ書いておく。
参考
- カーネルコンパイルの方法についてはUbuntuカーネルの最適化の手順をほぼそのまま踏襲させてもらいました。素晴らしい。
- gdb関係は山ほどあるので私的なメモとして以下のとおり列挙。
- kgdb関係はこのへん。
- カーネルモジュールを書くにあたっての事始めとして最速でkernel moduleのお勉強を。asm("int3");などをカーネルモジュールに突っ込んでおくとブレークします。
- 直接関係ないけどめも。きれいなemacsの作り方。