GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie debuggt man den Linux-Kernel mit GDB und QEMU?

Ich würde versuchen:

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

Die Verwendung der Option „-s“ lässt qemu auf Port tcp::1234 lauschen, mit dem Sie sich als localhost:1234 verbinden können, wenn Sie sich auf demselben Computer befinden. Die '-S'-Option von Qemu bewirkt, dass Qemu die Ausführung stoppt, bis Sie den Continue-Befehl geben.

Das Beste wäre wahrscheinlich, sich ein anständiges GDB-Tutorial anzusehen, um mit dem klarzukommen, was Sie tun. Dieser hier sieht ganz nett aus.


Schritt-für-Schritt-Verfahren auf Ubuntu 16.10-Host getestet

Um schnell von vorne anzufangen, habe ich ein minimales vollautomatisiertes QEMU + Buildroot-Beispiel erstellt unter:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md Major Schritte werden unten behandelt.

Besorgen Sie sich zuerst ein Root-Dateisystem rootfs.cpio.gz . Wenn Sie eine benötigen, ziehen Sie Folgendes in Betracht:

  • mindestens init -nur ausführbares Image:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579
  • ein interaktives Busybox-System:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Dann auf dem Linux-Kernel:

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

Angenommen, Sie möchten auf einem anderen Terminal innerhalb des Linux-Kernelbaums mit dem Debuggen ab start_kernel beginnen :

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'

und wir sind fertig!!

Für Kernel-Module siehe:Wie debuggt man Linux-Kernel-Module mit QEMU?

Für Ubuntu 14.04, GDB 7.7.1, hbreak wurde benötigt, break Software-Haltepunkte wurden ignoriert. In 16.10 nicht mehr der Fall. Siehe auch:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

Das chaotische disconnect und was danach kommt, um den Fehler zu umgehen:

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

Verwandte Threads:

  • https://sourceware.org/bugzilla/show_bug.cgi?id=13984 könnte ein GDB-Fehler sein
  • Remote 'g'-Paketantwort ist zu lang
  • http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org ist wie immer eine großartige Quelle für diese Probleme
  • 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

Bekannte Einschränkungen:

  • der Linux-Kernel unterstützt nicht (und lässt sich nicht einmal ohne Patches kompilieren) mit -O0 :Wie deoptimiere ich den Linux-Kernel und kompiliere ihn mit -O0?
  • GDB 7.11 wird Ihr Gedächtnis bei einigen Arten der Tab-Vervollständigung sprengen, selbst nach max-completions Fix:Unterbrechung der Tab-Vervollständigung bei großen Binärdateien Wahrscheinlich ein Sonderfall, der in diesem Patch nicht behandelt wurde. Also eine ulimit -Sv 500000 ist eine kluge Aktion vor dem Debuggen. Ist speziell explodiert, als ich mit der Tabulatortaste file<tab> abgeschlossen habe für filename Argument von sys_execve wie in:https://stackoverflow.com/a/42290593/895245

Siehe auch:

  • https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst offizielle Linux-Kernel-"Dokumentation"
  • Linux-Kernel-Live-Debugging, wie es gemacht wird und welche Tools verwendet werden?

Die Antwort von BjoernID hat bei mir nicht wirklich funktioniert. Nach der ersten Fortsetzung wird kein Breakpoint erreicht und bei Interrupt sehe ich Zeilen wie:

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

Ich denke, das hat etwas mit unterschiedlichen CPU-Modi zu tun (Real-Modus im BIOS vs. Long-Modus, wenn Linux gebootet hat). Wie auch immer, die Lösung besteht darin, QEMU zuerst ohne Wartezeit auszuführen (d.h. ohne -S ):

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

In meinem Fall musste ich während des Bootens etwas unterbrechen, also führte ich nach einigen Dezisekunden den gdb-Befehl aus. Wenn Sie mehr Zeit haben (z. B. wenn Sie ein manuell geladenes Modul debuggen müssen), spielt das Timing keine Rolle.

gdb ermöglicht es Ihnen, Befehle anzugeben, die beim Start ausgeführt werden sollen. Das macht die Automatisierung etwas einfacher. Um sich mit QEMU zu verbinden (das jetzt bereits gestartet sein sollte), eine Funktion zu unterbrechen und die Ausführung fortzusetzen, verwenden Sie:

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

Linux
  1. Analysieren Sie den Linux-Kernel mit ftrace

  2. Flatpak unter Linux:Was es ist und wie man Apps damit installiert

  3. So überprüfen Sie die Betriebssystem- und Linux-Version

  4. So erfassen Sie Terminalsitzungen und geben sie mit dem Linux-Skriptbefehl aus

  5. Wie kann man eine Linux-Kernel-Panik lesen, verstehen, analysieren und debuggen?

So verwenden Sie den Linux-Schlafbefehl mit Beispielen

So verwenden Sie den who-Befehl in Linux mit Beispielen

So überprüfen Sie die Kernel-Version in Linux

Finden Sie den Namen, die Version und die Kernel-Details der Linux-Distribution

So finden Sie Dateien mit dem fd-Befehl in Linux

So installieren und sichern Sie Apache mit HTTPS unter Fedora Linux