GNU/Linux >> Tutoriels Linux >  >> Linux

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

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 la même machine. L'option '-S' de Qemu arrête l'exécution de Qemu jusqu'à ce que vous donniez la commande continue.

La meilleure chose serait probablement de jeter un coup d'œil à un tutoriel GDB décent pour vous entendre avec ce que vous faites. Celui-ci a l'air plutôt sympa.


Procédure étape par étape testée sur l'hôte Ubuntu 16.10

Pour démarrer rapidement à partir de zéro, j'ai créé un exemple minimal de QEMU + Buildroot entièrement automatisé à l'adresse suivante :https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md les étapes sont couvertes ci-dessous.

Obtenez d'abord un système de fichiers racine rootfs.cpio.gz . Si vous en avez besoin, pensez à :

  • un minimum de init - image exécutable uniquement :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 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, depuis l'intérieur de l'arborescence du noyau Linux, en supposant que vous souhaitiez 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 terminé !!

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 ont été ignorés. Ce n'est plus le cas en 16.10. Voir aussi :https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

Le désordre disconnect et ce qui vient après pour contourner l'erreur :

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

Discussions associées :

  • https://sourceware.org/bugzilla/show_bug.cgi?id=13984 pourrait être un bogue GDB
  • La réponse du paquet "g" distant est trop longue
  • http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org est comme d'habitude une source géniale pour 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 prend pas en charge (et ne compile même pas sans correctifs) avec -O0 :Comment désoptimiser le noyau Linux et le compiler avec -O0 ?
  • GDB 7.11 vous explosera la mémoire sur certains types de complétion de tabulation, même après le max-completions correction :Interruption de l'achèvement des onglets pour les fichiers binaires volumineux Probablement un cas particulier qui n'était pas couvert par ce correctif. Donc un ulimit -Sv 500000 est une action sage avant le débogage. A explosé spécifiquement lorsque j'ai terminé l'onglet file<tab> pour le filename argument de sys_execve comme dans :https://stackoverflow.com/a/42290593/895245

Voir aussi :

  • https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst "documentation" officielle du noyau Linux
  • Débogage en direct du noyau Linux, comment cela se passe-t-il et quels outils sont utilisés ?

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 les différents modes de processeur (mode réel dans le BIOS par rapport au mode long lorsque Linux a démarré). Quoi qu'il en soit, la solution consiste à exécuter d'abord QEMU 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 pendant le démarrage, donc après quelques décisecondes, j'ai exécuté 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 les commandes qui doivent être exécutées au démarrage. Cela rend l'automatisation un peu plus facile. Pour vous connecter à QEMU (qui devrait déjà être démarré), interrompre une fonction et poursuivre l'exécution, utilisez :

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

Linux
  1. Regardez les commandes et les tâches avec la commande Linux watch

  2. Analyser le noyau Linux avec ftrace

  3. Comment déboguer des programmes C sous Linux à l'aide de gdb

  4. Flatpak sur Linux :qu'est-ce que c'est et comment installer des applications avec ?

  5. Comment vérifier la version du système d'exploitation et de Linux

Comment utiliser la commande Linux sleep avec des exemples

Comment utiliser la commande who sous Linux avec des exemples

Comment vérifier la version du noyau sous Linux

Trouver le nom de la distribution Linux, la version et les détails du noyau

Comment rechercher des fichiers avec la commande fd sous Linux

Comment installer et sécuriser Apache avec HTTPS sur Fedora Linux