web-dev-qa-db-fra.com

Comment déboguer le noyau Linux avec GDB et QEMU?

Je suis novice en développement de noyau et j'aimerais savoir comment exécuter/déboguer le noyau Linux à l'aide de QEMU et de gdb. En fait, je lis le livre de Robert Love, mais malheureusement, cela n'aide pas le lecteur à installer les outils appropriés pour exécuter ou déboguer le noyau ... J'ai donc suivi ce tutoriel http: //opensourceforu.efytimes .com/2011/02/kernel-development-debugging-using-Eclipse/ . J'utilise Eclipse en tant que IDE pour développer sur le noyau, mais je voulais d'abord le faire fonctionner sous QEMU/gdb. Donc ce que j'ai fait jusqu'à présent était:

1) Compiler le noyau avec:

make defconfig (then setting the CONFIG_DEBUG_INFO=y in the .config)
make -j4

2) Une fois la compilation terminée, je lance Qemu en utilisant:

qemu-system-x86_64 -s -S /dev/zero -kernel /Arch/x86/boot/bzImage

qui lancent le noyau à l'état "arrêté"

3) Donc je dois utiliser gdb, j'essaye la commande suivante:

gdb ./vmlinux

qui fonctionne correctement mais ... Maintenant, je ne sais pas quoi faire ... Je sais que je dois utiliser le débogage distant sur le port 1234 (port par défaut utilisé par Qemu), en utilisant vmlinux comme fichier de table de symboles pour débogage.

Ma question est donc la suivante: que dois-je faire pour exécuter le noyau sur Qemu, y attacher mon débogueur et le faire travailler ensemble pour me faciliter la vie avec le développement du noyau?.

28
E-Kami

J'essaierais:

(gdb) target remote localhost:1234
(gdb) continue

L'utilisation de l'option -s permet à qemu d'écouter sur le port tcp :: 1234, auquel vous pouvez vous connecter en tant que localhost: 1234 si vous êtes sur le même ordinateur. L'option '-S' de Qemu fait que Qemu arrête l'exécution jusqu'à ce que vous donniez la commande continue.

La meilleure chose à faire serait probablement de jeter un coup d’œil à un didacticiel GDB décent pour vous entendre avec ce que vous faites. Celui-ci a l'air assez gentil.

24
BjoernD

Procédure pas à pas testée sur l'hôte Ubuntu 16.10

Pour commencer rapidement à partir de zéro, j'ai créé un exemple entièrement automatisé QEMU + Buildroot à l'adresse: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a3a380d1607df0b2a3701/gdb-step- .md Les principales étapes sont décrites ci-dessous.

Commencez par obtenir un système de fichiers racine rootfs.cpio.gz. Si vous en avez besoin, considérez:

Puis sur le noyau 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

Sur un autre terminal, à partir de l’arbre du noyau Linux, si vous souhaitez commencer le débogage à partir de 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'

et nous avons fini !!

Pour les modules du noyau, voir: Comment déboguer les modules du noyau Linux avec QEMU?

Pour Ubuntu 14.04, GDB 7.7.1, hbreak était nécessaire, break, les points d'arrêt logiciels étaient ignorés. Ce n'est plus le cas en 16.10. Voir aussi: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

La disconnect désordonnée et ce qui suit sont pour contourner l'erreur:

Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000

Discussions connexes:

Limites connues:

Voir également:

La réponse de BjoernID n'a pas vraiment fonctionné pour moi. Après la première continuation, aucun point d'arrêt n'est atteint et sur interruption, je verrais des lignes telles que:

0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]

Je suppose que cela a quelque chose à voir avec différents modes de processeur (mode réel dans le BIOS vs mode long lorsque Linux a démarré). Quoi qu’il en soit, la solution consiste à exécuter QEMU d’abord sans attendre (c’est-à-dire sans -S):

qemu-system-x86_64 -enable-kvm -kernel Arch/x86/boot/bzImage -cpu SandyBridge -s

Dans mon cas, j'avais besoin de casser quelque chose au démarrage, donc après quelques secondes, j'ai exécuté la commande gdb. Si vous avez plus de temps (par exemple, vous devez déboguer un module chargé manuellement), le minutage importe peu.

gdb vous permet de spécifier les commandes à exécuter au démarrage. Cela facilite l'automatisation. Pour vous connecter à QEMU (qui devrait maintenant déjà être démarré), interrompez une fonction et poursuivez son exécution, utilisez:

gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux
3
Lekensteyn

Lorsque vous essayez de démarrer vmlinux exe en utilisant gdb, la première chose à faire sur gdb est d'émettre des cmds:

(gdb) hôte local distant cible: 1234

(gdb) break start_kernel

(continuer)

Cela cassera le noyau à start_kernel.

2
Ritesh

Quant à moi, la meilleure solution pour déboguer le noyau est d’utiliser gdb à partir d’environnement Eclipse. Vous devez simplement définir le port approprié pour gdb (doit être identique à celui spécifié dans la chaîne de lancement qemu) dans la section de débogage distant. Voici le manuel: http://www.sw-at.com/blog/2011/02/11/linux-kernel-development-and-debugging-using-Eclipse-cdt/

1
Alex Hoppus