Skip to main content.
Google custom search

NetBSD ドキュメンテーション: GDB を使い NetBSD カーネルをデバッグする HOWTO

KGDB の使用方法


KGDB の使用方法

概要 (トップ)

NetBSD カーネルに含まれている DDB デバッガーは、クラッシュ・トレースバック を入手したり、変数の値の検査、その他のこまかいデバッグのために、役に立ちま す。しかしながら、もし、真剣にカーネルをハックしているのであれば、DDB のか わりに、リモートデバッガー KGDB が動作するように設定したいと思うでしょう。

DDB に対する KGDB の利点は、ディスアセンブルされたマシンコードでなく カーネルの ソースコード を見ることができることです。実際のところ、 ほとんどすべての GDB の機能が使用可能で、gdb のいくつかのグラフィカル インターフェースを使うこともできます(例えば devel/ddd など)。

事前に準備しておくこと (トップ)

  • 同一アーキテクチャーで NetBSD の動作しているマシン二台(オブジェクトコード のフォーマットも同一であること):

    • TARGET - デバッグするカーネルを実行するマシン

    • REMOTE - gdb を実行、表示するマシン

    あるアーキテクチャーのホストで、他のアーキテクチャーのターゲット用の gdb を構築することも可能です。しかし、今のところこれについてはここでの対象範囲外です。

  • 空きのシリアルポートが両方のマシンに存在すること。

  • null モデムケーブル (詳しくは NetBSD シリアルポート入門参照)。

  • カーネルの構築とインストール、そして gdb の使用法についての知識

手順 (トップ)

(以下の文中では、REMOTE マシン上(gdb が動作している)で /dev/tty01 を、TARGET マシン(デバッグされる)では /dev/tty00 を使用していると仮定して説明します。 お使いのマシンに合わせて、シリアルポートのデバイスを適切なもの─たとえば /dev/dty00 ─に置き換える必要があるかもしれません。

  1. KGDB を有効にしたカーネルの構築

    (注意: たぶん、これが REMOTE マシン上でカーネルを構築する最良の方法 でしょう。これで、デバッグする時には、すべての必要なソースファイルと シンボルファイルはすでに準備されています。)

    • TARGET マシンのためにカーネルのコンフィグファイル内の以下の行を コメントアウトしてください。

        #options 	DDB			# in-kernel debugger
        #options 	DDB_HISTORY_SIZE=100	# enable history editing

      以下の三行をアンコメントアウト(あるいは追加) してください。

        options 	KGDB		# remote debugger
        options 	"KGDB_DEVNAME=\"com\"",KGDB_DEVADDR=0x3f8,KGDB_DEVRATE=9600
        makeoptions	DEBUG="-g"	# compile full symbol table

      TARGET マシン上で使用するシリアルポートの IO アドレス(0x3f8 は tty00、 0x2f8 は tty01 用です)に一致するように、 KGDB_DEVADDR を変更してください。 それから、 KGDB_DEVRATE を、使用するビットレートに一致させてください。

    • TARGET マシンのカーネルの設定と 構築をおこなってください。

  2. TARGET マシンの準備

    ファイル netbsd を、カーネルを構築したディレクトリーから TARGET マシンの ルートディレクトリーにコピーしてください。このカーネルを REMOTE マシンに インストールしてはいけません。(特に、両方のマシンで同じ tty を使っている 時には注意してください!)

  3. REMOTE マシンの準備

    • TARGET マシンでカーネルを構築したのであれば、 /usr/src/sys すべてを、 REMOTE マシンにコピーしてください。(注意: TARGET マシンのディレクトリーを単に NFS マウントしてはいけません。 gdb がブレークポイントで停止した時に、TARGET マシン上の nfsd を含むすべてのプロセスは停止します。)

    • REMOTE マシン上で使う予定の(そして REMOTE マシンでだけ使う) tty の ために /etc/ttys を変更してください。 例えば以下のように。

        tty01 "/usr/libexec/getty std.9600" unknown off local

      ここで重要なのは、off (これで、init がこのポートで getty を起動することはありません)と localです。なぜならば、 ttyflags は、 /etc/ttys に従ってブート時にポートのデフォルトを設定します。 そして、gdb を使うには、DTR を待たないようにするために localが設定されていなければなりません。

      std.9600を別のビットレートに変更したい場合もあるかもしれません。 この場合、ビットレートは、gdb で設定する remotebaudrate (後で説明します)と同様に、 TARGET 用のカーネルオプションで設定したレートと一致していなければなりません。 /etc/gettytab の中に、 あなたが使う名前と一致するエントリーがあることを確認してください。

    • REMOTE マシンをリブートするか、 ttyflags を起動し /etc/ttys を再読み込みさせてください。(kill -1 1 で十分かもしれません。しかし、 /etc/ttys の項目の順番を変更したことにより、 init が混乱する可能性があります)。

  4. null モデムケーブルを使い、 シリアルポートに接続してください。

  5. TARGET マシンをリブートし、ブートローダーのメッセージが表示されたら すぐに、スペースキーを押してください。そして、次のコマンドを入力して ください。

      boot -d

    これによりカーネルがロードされます。 waiting for kgdbというメッセージが表示された後、 TARGET は停止します。

  6. REMOTE マシン側で、 カーネルを構築したディレクトリー (一般的には /usr/src/sys/arch/something/compile/config-name) に移動し、gdb を起動します。

    # gdb netbsd.gdb

    数秒後、 (gdb) プロンプトが表示されるはずです。

  7. gdb のいくつかのフラグを設定する

      # いつでも Ctrl-C により TARGET を停止させることができるようにする。
      (gdb) set remotebreak 1
      # gdb の使用するボーレートを設定する。(デフォルトは 9600、
      # TARGET にインストールされたカーネルの設定と一致していること)
      (gdb) set remotebaud 9600
      # シリアル上でラインエラーが発生した場合の再送速度を速くする。
      (gdb) set remotetimeout 3
  8. TARGET マシンに接続します(REMOTEマシン側で tty01 を使用していると 仮定しています)

      target remote /dev/tty01

    以下のようなメッセージが表示されます。

      Remote debugging using /dev/tty01
      kgdb_connect (verbose=1) at 	../../../../arch/i386/i386/kgdb_machdep.c:244
      244             if (verbose)
      (gdb)

    もし、これらのメッセージが表示されるかわりに、 GDB がhangしているようなら、 シリアルハードウェア、ケーブル、あるいは設定に何か間違いがあります。 トラブルシューティングのセクションを参照してください。

  9. さて、プロンプトが表示されれば、ハックする準備はできています。 ブレークポイントを設定したり、データを確認したり、一ステップ毎に実行する ことができます。ちょうど、ローカルマシン上で動作しているユーザーレベル アプリケーションを gdb でデバッグするのと同じです。カーネルのブートプロ セスを続行させるには、contを使ってください。後でデバッガーにもどるため には、Ctrl-C を押してください。

  10. 5 から 7 の手順を自動化するためには、カーネルを構築するディレクトリーに 以下の内容のファイル .gdbinit を作成してください。

      file netbsd.gdb
      set remotebreak 1
      set remotebaud 9600
      target remote /dev/tty01

    さて、これでgdbとタイプするだけで、 デバッグを始めることができます。

トラブルシューティング (トップ)

もし、うまく動作しない場合は、以下の事を試してみてください。

  • -d を指定せずに TARGET マシンをリブートしてください。 デバイスのプローブ時に以下のようなメッセージが表示されるはずです。 二行目が表示されていなければ、 構築したカーネルでは KGDB が有効になっていないか、 間違ったカーネルを使用しています。

      com0 at isa0 port 0x3f8-0x3ff irq4: ns16550a, working fifo
      com0: kgdb
  • シリアルポートとケーブルが normalのアプリケーションで動作することを確認してください。 KGDB を無効にしたカーネルで TARGET マシンをリブートし、二つのマシン間で tip を実行してみてください。もし、 tip について知らないのであれば、 以下の簡単な手順を参考にしてください。

    • 以下の行を、TARGET と REMOTE 両マシンの /etc/remote に追加してください。

      	tty00-9600:dv=/dev/tty00:br#9600:pa=none:dc:
      	tty01-9600:dv=/dev/tty01:br#9600:pa=none:dc:
    • TARGET マシン上で tip tty00-9600 を、REMOTE マシン上で tip tty01-9600 を実行してください。

    • 両方のマシンのキーボードで適当な文字を入力してください。 文字は他のマシンのディスプレイに表示されるはずです。

  • /etc/ttys の中の、 自分が使っている tty の行を再度確認し、 それが有効かどうかを確認するためにリブートしてください。

  • 今まで書いてた文章の中では、root で作業している事を仮定していました。 一般ユーザーの場合、tip と gdb は動作しません。(/dev/tty0* のパーミッションに依存します)。もちろん、root での作業は、一般的にはおすすめできません。 かわりに、以下のようにしてください。

    1. /dev/tty0* のグループを wheel にしてください(そうなっていなければ)

    2. あなたのユーザー名を、/etc/groupwheel 行に追加してください

    3. あなたのユーザー名を、/etc/groupdialer 行に追加してください

    (2) により、gdb のプロセスが(そして、 あなたが起動している他のプロセスも)、tty をオープンできるようになる。(3) により、 tip を起動することができるようになる。

一般的な注意 (トップ)

  1. コマンドを入力してから反応が返ってくるまでに、時々長い時間がかかる ことがあります。これは、おそらくシリアルコネクション上の不正なデータの せいです。みじかい休止と再送の後、すべて正常にもどります。 remotetimeout の値をデフォルトの 20 秒より短かく設定するとよいでしょう。 (これはある人から報告がありました。(彼の場合は)カーネルの printf() が コマンドの間に実行されたことが原因でした。これにより gdb のデータがこわれ たようです)。

  2. カーネルが高優先度の割り込み(機種依存)ロック中は、Ctrl-C は動作しません。 例えば、i386 では、splimp() の中の永久ループを停止させることはできません。 しかし、ブレークポイントを、そのループの前にセットすれば、そこを一ステップ ずつ実行することができます。


Back to NetBSD ドキュメンテーション: カーネル