Proverei:
(gdb) target remote localhost:1234
(gdb) continue
Usando l'opzione '-s' qemu resta in ascolto sulla porta tcp::1234, alla quale puoi connetterti come localhost:1234 se sei sulla stessa macchina. L'opzione '-S' di Qemu fa sì che Qemu interrompa l'esecuzione finché non dai il comando continue.
La cosa migliore sarebbe probabilmente dare un'occhiata a un tutorial GDB decente per andare d'accordo con quello che stai facendo. Questo sembra piuttosto carino.
Procedura dettagliata testata sull'host Ubuntu 16.10
Per iniziare rapidamente da zero, ho creato un esempio minimo di QEMU + Buildroot completamente automatizzato su:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md Major i passaggi sono descritti di seguito.
Per prima cosa prendi un filesystem root rootfs.cpio.gz
. Se ne hai bisogno, considera:
- un
init
minimo -solo immagine eseguibile:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579 - un sistema interattivo Busybox:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902
Quindi sul kernel 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
Su un altro terminale, dall'interno dell'albero del kernel di Linux, supponendo di voler avviare il debug da 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'
e abbiamo finito!!
Per i moduli del kernel vedi:Come eseguire il debug dei moduli del kernel Linux con QEMU?
Per Ubuntu 14.04, GDB 7.7.1, hbreak
era necessario, break
i punti di interruzione del software sono stati ignorati. Non è più il caso in 16.10. Vedi anche:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944
Il disordinato disconnect
e ciò che viene dopo è per aggirare l'errore:
Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
Discussioni correlate:
- https://sourceware.org/bugzilla/show_bug.cgi?id=13984 potrebbe essere un bug di GDB
- La risposta del pacchetto 'g' remoto è troppo lunga
- http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org è come al solito una fantastica fonte per questi problemi
- 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
Limitazioni note:
- il kernel Linux non supporta (e non compila nemmeno senza patch) con
-O0
:Come de-ottimizzare il kernel Linux e compilarlo con -O0? - GDB 7.11 ti lascerà a bocca aperta su alcuni tipi di completamento delle schede, anche dopo l'
max-completions
correzione:interruzione del completamento della scheda per file binari di grandi dimensioni Probabilmente un caso angolare che non era coperto in quella patch. Quindi unulimit -Sv 500000
è un'azione saggia prima del debug. È esploso in particolare quando ho completato la schedafile<tab>
per ilfilename
argomento disys_execve
come in:https://stackoverflow.com/a/42290593/895245
Vedi anche:
- https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst "documentazione" ufficiale del kernel Linux
- Debug in tempo reale del kernel Linux, come viene eseguito e quali strumenti vengono utilizzati?
La risposta di BjoernID non ha funzionato davvero per me. Dopo la prima continuazione, non viene raggiunto alcun punto di interruzione e all'interruzione vedrei righe come:
0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]
Immagino che questo abbia qualcosa a che fare con diverse modalità della CPU (modalità reale nel BIOS rispetto alla modalità lunga quando Linux è stato avviato). Ad ogni modo, la soluzione è eseguire prima QEMU senza attendere (cioè senza -S
):
qemu-system-x86_64 -enable-kvm -kernel arch/x86/boot/bzImage -cpu SandyBridge -s
Nel mio caso, avevo bisogno di interrompere qualcosa durante l'avvio, quindi dopo alcuni decisicond, ho eseguito il comando gdb. Se hai più tempo (ad esempio devi eseguire il debug di un modulo che viene caricato manualmente), allora i tempi non contano davvero.
gdb
consente di specificare i comandi che devono essere eseguiti all'avvio. Questo rende l'automazione un po' più facile. Per connettersi a QEMU (che ora dovrebbe essere già avviato), interrompere una funzione e continuare l'esecuzione, utilizzare:
gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux