このブログは、株式会社フィックスターズのエンジニアが、あらゆるテーマについて自由に書いているブログです。
QEMUをカーネルの開発に使うことのメリットの1つとして、GDBによるデバッグが簡単にできることがあります。これは、GDBのリモートデバッグ機能を使用します。リモートデバッグ機能は、もとをたどれば、別のマシンで動いている(主に)組込みシステムをデバッグするために開発された機能で、対象システムにGDBと通信するためのスタブを組み込み、シリアルラインを介して通信してデバッグするというものでした。現在では、TCP/IPでの通信もサポートされており、QEMUにはそのスタブが組み込まれており、QEMU上で実行するプログラムをGDBでデバッグできるようになっています。
GDBでのLinuxカーネルのデバッグについては、今は以下にしっかりとした情報がまとまっていました。
https://www.kernel.org/doc/html/v4.12/dev-tools/gdb-kernel-debugging.html
ここに書かれている手順に従ってやってみましょう。
カーネルのコンフィグでは、CONFIG_GDB_SCRIPTSと(もしあれば)CONFIG_FRAME_POINTERをセットし、CONFIG_DEBUG_INFO_REDUCEDは切る、とのことです。これらのパラメータは、Kernel hackingからCompile-time checks and compiler optionsに移動したところにあります。以下は menuconfig の画面になりますが、
という対応になっています。なお、2~5行目が表示されていない場合は、1行目の Compile the kernel with debug info を選択すると表示されます。
ちなみに、パラメータがどこのあるかわからない場合は、検索することもできます。menuconfig ではキーボードで / を入力すると、以下の画面が出てきますので、検索したいパラメータまたはキーワードを入力します。
すると、以下のようにどこにあるか (Location:) どのように表示されているか (Prompt:) を教えてくれます。
QEMUをGDBと接続するには、-s オプションを付けてQEMUを起動します。実行開始時からデバッグしたい場合は、-S (大文字のS) オプションもつけます。
では、早速 -s -S オプションをつけて、QEMU を実行してみましょう。
% qemu/x86_64-softmmu/qemu-system-x86_64 -s -S -m 256 -nographic -kernel linux-stable/arch/x86_64/boot/bzImage -append console=ttyS0 -initrd initrd.img
待機状態になっていますので、何も起こりません。別の端末からGDBを実行します。
なにやら怒られてしまいました。.gdbinitにadd-auto-load-safe-pathを設定しなさい、ということなので、その通りにします。
~% cat .gdbinit
add-auto-load-safe-path /home/shui/src/linux-stable/scripts/gdb/vmlinux-gdb.py
もう一度GDBを起動しますが、今度は違うエラーが出ます。
解決方法を探したところ、以下にある情報で解決できました:
https://github.com/cyrus-and/gdb-dashboard/issues/1
ホストOSはCentOS 7で、付属のGDBバージョン7.6ではちょっと古いのが原因だったのですが、~/.gdbinit.dにgdb/python/lib/gdb/FrameDecorator.pyを置き、.gdbinitの中身を以下にするとエラーはなくなりました。
% cat .gdbinit
python gdb.COMPLETE_EXPRESSION = gdb.COMPLETE_SYMBOL
python
import imp
gdb.FrameDecorator = imp.new_module('FrameDecorator')
end
#
add-auto-load-safe-path /home/shui/src/linux-stable/scripts/gdb/vmlinux-gdb.py
GDBの側でQEMUと接続するには target remote :1234 と入力します。その後で、適当なブレークポイントを設定し、c (continue) と打てば、QEMU側で実行が始まり、ブレークポイントに到達したところで、GDBに戻ります。
ブレークポイント削除後にc を打てば、QEMU上でLinuxカーネルは実行を継続します。実行中にカーネルの実行を中断したければ、GDB側で Ctrl-C を打つと、GDBのプロンプトが表示され、カーネルの実行状態を調べることができます。
今回は、QEMUとGDBを接続し、GDBでLinuxカーネルのデバッグをする方法を紹介しました。CONFIG_GDB_SCRIPTS は、カーネル内の状態を表示するためのコマンドを提供しており、GDBで実行できるコマンドは apropos lx で表示できます。カーネルの実行時の内部状態を調べるのはこれまで面倒でしたが、かなり容易に調べられるようになっていますね。
keisuke.kimura in Livox Mid-360をROS1/ROS2で動かしてみた
Sorry for the delay in replying. I have done SLAM (FAST_LIO) with Livox MID360, but for various reasons I have not be...
Miya in ウエハースケールエンジン向けSimulated Annealingを複数タイルによる並列化で実装しました
作成されたプロファイラがとても良さそうです :) ぜひ詳細を書いていただきたいです!...
Deivaprakash in Livox Mid-360をROS1/ROS2で動かしてみた
Hey guys myself deiva from India currently i am working in this Livox MID360 and eager to knwo whether you have done the...
岩崎システム設計 岩崎 満 in Alveo U50で10G Ethernetを試してみる
仕事の都合で、検索を行い、御社サイトにたどりつきました。 内容は大変参考になりま...
Prabuddhi Wariyapperuma in Livox Mid-360をROS1/ROS2で動かしてみた
This issue was sorted....