試してみます:
(gdb) target remote localhost:1234
(gdb) continue
「-s」オプションを使用すると、qemu はポート tcp::1234 でリッスンします。同じマシンにいる場合は、このポートに localhost:1234 として接続できます。 Qemu の「-S」オプションは、continue コマンドが与えられるまで Qemu の実行を停止します。
最善の方法は、適切な GDB チュートリアルを見て、自分がしていることに慣れることです。これはなかなか良さそうです。
段階的な手順は Ubuntu 16.10 ホストでテスト済み
ゼロからすばやく始めるために、完全に自動化された最小限の QEMU + Buildroot の例を作成しました:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md手順については以下で説明します。
最初にルートファイルシステム rootfs.cpio.gz
を取得します .必要な場合は、以下を検討してください:
- 最小限の
init
-実行可能イメージのみ:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579 - Busybox インタラクティブ システム:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902
次に、Linux カーネルで:
git checkout v4.15
make mrproper
make x86_64_defconfig
cat <<EOF >.config-fragment
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
EOF
./scripts/kconfig/merge_config.sh .config .config-fragment
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
-initrd rootfs.cpio.gz -S -s \
-append nokaslr
別の端末で、Linux カーネル ツリー内から start_kernel
からデバッグを開始するとします。 :
gdb \
-ex "add-auto-load-safe-path $(pwd)" \
-ex "file vmlinux" \
-ex 'set arch i386:x86-64:intel' \
-ex 'target remote localhost:1234' \
-ex 'break start_kernel' \
-ex 'continue' \
-ex 'disconnect' \
-ex 'set arch i386:x86-64' \
-ex 'target remote localhost:1234'
これで完了です!!
カーネル モジュールについては、QEMU を使用して Linux カーネル モジュールをデバッグする方法を参照してください。
Ubuntu 14.04、GDB 7.7.1、hbreak
の場合 break
が必要でした ソフトウェア ブレークポイントは無視されました。 16.10 ではもうそうではありません。参照:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944
乱雑な disconnect
その後、エラーを回避する必要があります:
Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
関連スレッド:
- https://sourceware.org/bugzilla/show_bug.cgi?id=13984 は GDB のバグの可能性があります
- リモート 'g' パケット応答が長すぎます
- http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org は、いつものようにこれらの問題の優れた情報源です
- https://lists.nongnu.org/archive/html/qemu-discuss/2014-10/msg00069.html
nokaslr
:https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb/421287#421287
既知の制限:
- Linux カーネルは
-O0
をサポートしていません (パッチなしではコンパイルさえしません)。 :Linux カーネルを最適化解除して -O0 でコンパイルする方法 - GDB 7.11 では、
max-completions
の後でも、一部の種類のタブ補完でメモリが吹き飛ばされます。 修正:大きなバイナリのタブ完了割り込み そのパッチでカバーされていないいくつかのまれなケースの可能性があります。だからulimit -Sv 500000
デバッグする前の賢明な行動です。特にfile<tab>
をタブで完了したときに爆発しましたfilename
の場合sys_execve
の引数 のように:https://stackoverflow.com/a/42290593/895245
こちらもご覧ください:
- https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst 公式 Linux カーネル「ドキュメント」
- Linux カーネルのライブ デバッグ、その方法と使用するツール
BjoernID の答えは、私にはうまくいきませんでした。最初の継続の後、ブレークポイントに到達せず、割り込み時に次のような行が表示されます:
0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]
これは、さまざまな CPU モード (BIOS のリアル モードと Linux が起動したときのロング モード) に関係があると思います。とにかく、解決策は最初に QEMU を待機せずに実行することです (つまり、-S
なしで) ):
qemu-system-x86_64 -enable-kvm -kernel arch/x86/boot/bzImage -cpu SandyBridge -s
私の場合、起動中に何かを中断する必要があったため、数デシ秒後に gdb コマンドを実行しました。もっと時間があれば (たとえば、手動でロードされたモジュールをデバッグする必要がある場合)、タイミングはあまり重要ではありません。
gdb
起動時に実行するコマンドを指定できます。これにより、自動化が少し簡単になります。 QEMU (既に開始されているはず) に接続し、関数を中断して実行を継続するには、次を使用します。
gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux