Comment déboguer le noyau Linux avec GDB et QEMU?
je suis nouveau dans le développement du noyau et je voudrais savoir comment exécuter/déboguer le noyau linux en utilisant QEMU et gdb. Je suis en train de lire le livre de Robert Love mais malheureusement il n'aide pas le lecteur sur la façon d'installer les outils appropriés pour exécuter ou déboguer le noyau... Donc ce que j'ai fait était de suivre ce tutoriel http://opensourceforu.efytimes.com/2011/02/kernel-development-debugging-using-eclipse / . J'utilise eclipse comme IDE pour développer sur le noyau, mais je voulais d'abord pour que ça fonctionne sous QEMU / gdb. Alors 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, J'exécute Qemu en utilisant:
qemu-system-x86_64 -s -S /dev/zero -kernel /arch/x86/boot/bzImage
qui lance le noyau dans l'état" stopped
3) je dois donc utiliser gdb, j'essaie la commande suivante:
gdb ./vmlinux
qui l'exécute correctement mais... Maintenant, je ne sais pas quoi faire... Je sais que j'ai pour utiliser le débogage à distance sur le port 1234 (port par défaut utilisé par Qemu), en utilisant le vmlinux comme fichier de table de symboles pour le débogage.
donc ma question Est: Que dois-je faire pour lancer le noyau sur Qemu, y attacher mon Débogueur et ainsi, les faire travailler ensemble pour rendre ma vie plus facile avec le développement du noyau.
5 réponses
je voudrais essayer:
(gdb) target remote localhost:1234
(gdb) continue
en utilisant l'option '-s' rend qemu listen sur le port tcp::1234, auquel vous pouvez vous connecter comme localhost:1234 si vous êtes sur la même machine. L'option '-S' de Qemu permet à Qemu d'arrêter l'exécution jusqu'à ce que vous donniez la commande continue.
la meilleure chose serait probablement de jeter un oeil à un tutoriel gdb décent pour s'entendre avec ce que vous faites. celui-ci est très joli.
procédure étape par étape Testée sur Ubuntu 16.10 host
pour démarrer à partir de zéro rapidement, j'ai fait un minimum entièrement automatisé qemu + Buildroot exemple à: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md les principales étapes sont décrites ci-dessous.
obtenez D'abord un système de fichiers racine rootfs.cpio.gz
. Si vous avez besoin d'un, prendre en considération:
- a minimal
init
- seulement image exécutable: https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579 - un système interactif Busybox: https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902
puis le 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, à l'intérieur de L'arborescence du noyau Linux, en supposant que vous voulez commencer à déboguer à 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 c'est 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
, break
logiciel des points d'arrêt ont été ignorés. Pas le cas aujourd'hui dans 16.10. Voir aussi: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm / + bug / 901944
Le désordre disconnect
et ce qui viendra après elle sont pour contourner le message d'erreur:
Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
fils connexes:
- https://sourceware.org/bugzilla/show_bug.cgi?id=13984 pourrait être un bug GDB
- à Distance "g" la réponse par paquet est trop longue
- http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org est comme d'habitude une super source de ces problèmes
- 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
limitations connues:
- le noyau Linux ne supporte pas (et ne compile même pas sans correctifs) avec
-O0
: comment dés-optimiser le noyau Linux et le compiler avec-O0? - GDB 7.11 va souffler votre mémoire sur certains types de completion tab, même après le
max-completions
fix: interruption de completion Tab pour les binaires de grande taille probablement un cas de coin qui n'a pas été couvert dans ce patch. Ainsi, unulimit -Sv 500000
est une action Sage avant le débogage. Soufflé spécifiquement lorsque j'ai complétéfile<tab>
pour lefilename
argument desys_execve
comme dans: https://stackoverflow.com/a/42290593/895245
voir aussi:
la réponse de BjoernID n'a pas vraiment fonctionné pour moi. Après la première continuation, aucun point de rupture n'est atteint et à l'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 CPU (mode réel dans le BIOS vs. mode long quand Linux a démarré). Quoi qu'il en soit, la solution est D'exécuter D'abord QEMU sans attendre (i.e. 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 pendant boot, donc après quelques décisecondes, j'ai lancé la commande gdb. Si vous avez plus de temps (par exemple, vous devez déboguer un module qui est chargé manuellement), alors le timing n'a pas vraiment d'importance.
gdb
vous permet de spécifier des commandes qui doivent être exécutées au démarrage. Cela rend l'automatisation un peu plus facile. Pour se connecter à QEMU (qui devrait déjà être démarré), casser une fonction et continuer l'exécution, utilisez:
gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux
lorsque vous essayez de lancer vmlinux exe en utilisant gdb, alors la première chose sur gdb est de lancer cmds:
(gdb) cible remote localhost: 1234
(gdb) break start_kernel
(suite)
cela cassera le noyau à start_kernel.
comme pour moi la meilleure solution pour déboguer le noyau - est d'utiliser gdb de L'environnement Eclipse. Vous devez juste définir le port approprié pour gdb (doit être le même avec un que vous avez spécifié dans la chaîne de lancement qemu) dans la section de débogage à distance. Voici le manuel: http://www.sw-at.com/blog/2011/02/11/linux-kernel-development-and-debugging-using-eclipse-cdt/