Zkusil bych:
(gdb) target remote localhost:1234
(gdb) continue
Použití volby '-s' způsobí, že qemu naslouchá na portu tcp::1234, ke kterému se můžete připojit jako localhost:1234, pokud jste na stejném počítači. Volba '-S' Qemu způsobí, že Qemu zastaví provádění, dokud nezadáte příkaz continue.
Nejlepší by pravděpodobně bylo podívat se na slušný tutoriál GDB, abyste se sžili s tím, co děláte. Tenhle vypadá docela pěkně.
Postup krok za krokem testovaný na hostiteli Ubuntu 16.10
Abych mohl rychle začít od nuly, vytvořil jsem minimální plně automatizovaný příklad QEMU + Buildroot na:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gbuggingmdb-step kroky jsou popsány níže.
Nejprve získejte kořenový souborový systém rootfs.cpio.gz
. Pokud jej potřebujete, zvažte:
- minimálně
init
-pouze spustitelný obrázek:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579 - Interaktivní systém Busybox:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902
Pak na linuxovém jádře:
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
Na jiném terminálu, ze stromu jádra Linuxu, předpokládejme, že chcete začít s laděním od 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'
a máme hotovo!!
Moduly jádra viz:Jak ladit moduly jádra Linuxu pomocí QEMU?
Pro Ubuntu 14.04, GDB 7.7.1, hbreak
bylo potřeba, break
softwarové body přerušení byly ignorovány. Od 16.10 to neplatí. Viz také:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944
Nepořádný disconnect
a co přijde po tom, je obejít chybu:
Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
Související vlákna:
- https://sourceware.org/bugzilla/show_bug.cgi?id=13984 může být chyba GDB
- Odpověď vzdáleného paketu 'g' je příliš dlouhá
- http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org je jako obvykle skvělým zdrojem těchto problémů
- 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
Známá omezení:
- jádro Linuxu nepodporuje (a ani se nezkompiluje bez oprav) s
-O0
:Jak de-optimalizovat linuxové jádro a zkompilovat jej s -O0? - GDB 7.11 vám při některých typech dokončování karet vybije paměť, a to i po
max-completions
oprava:Přerušení dokončování tabulátoru pro velké binární soubory Pravděpodobně nějaké rohové pouzdro, které nebylo pokryto v tomto patchi. Takžeulimit -Sv 500000
je moudrá akce před laděním. Vybuchlo konkrétně, když jsem dokončil kartufile<tab>
profilename
argumentsys_execve
jako na:https://stackoverflow.com/a/42290593/895245
Viz také:
- https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst oficiální "dokumentace" linuxového jádra
- Linuxové jádro živé ladění, jak se to provádí a jaké nástroje se používají?
Odpověď BjoernID pro mě opravdu nefungovala. Po prvním pokračování není dosaženo bodu přerušení a při přerušení bych viděl řádky jako:
0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]
Myslím, že to má něco společného s různými režimy CPU (reálný režim v BIOSu vs. dlouhý režim, když se Linux nabootoval). Řešením je každopádně nejprve spustit QEMU bez čekání (tj. bez -S
):
qemu-system-x86_64 -enable-kvm -kernel arch/x86/boot/bzImage -cpu SandyBridge -s
V mém případě jsem potřeboval během bootování něco zlomit, takže po několika decisekundách jsem spustil příkaz gdb. Pokud máte více času (např. potřebujete ladit modul, který se načítá ručně), pak na načasování opravdu nezáleží.
gdb
umožňuje zadat příkazy, které se mají spustit při spuštění. Tím je automatizace o něco jednodušší. Chcete-li se připojit ke QEMU (která by již měla být spuštěna), přerušit funkci a pokračovat ve vykonávání, použijte:
gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux