GNU/Linux >> Znalost Linux >  >> Linux

Jak ladit linuxové jádro pomocí GDB a QEMU?

Zkusil bych:

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

Použití volby '-s' způsobí, že qemu naslouchá na portu tcp::1234, ke kterému se můžete připojit jako localhost:1234, pokud jste na stejném počítači. Volba '-S' Qemu způsobí, že Qemu zastaví provádění, dokud nezadáte příkaz continue.

Nejlepší by pravděpodobně bylo podívat se na slušný tutoriál GDB, abyste se sžili s tím, co děláte. Tenhle vypadá docela pěkně.


Postup krok za krokem testovaný na hostiteli Ubuntu 16.10

Abych mohl rychle začít od nuly, vytvořil jsem minimální plně automatizovaný příklad QEMU + Buildroot na:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gbuggingmdb-step kroky jsou popsány níže.

Nejprve získejte kořenový souborový systém rootfs.cpio.gz . Pokud jej potřebujete, zvažte:

  • minimálně init -pouze spustitelný obrázek:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579
  • Interaktivní systém Busybox:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Pak na linuxovém jádře:

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

Na jiném terminálu, ze stromu jádra Linuxu, předpokládejme, že chcete začít s laděním od 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'

a máme hotovo!!

Moduly jádra viz:Jak ladit moduly jádra Linuxu pomocí QEMU?

Pro Ubuntu 14.04, GDB 7.7.1, hbreak bylo potřeba, break softwarové body přerušení byly ignorovány. Od 16.10 to neplatí. Viz také:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

Nepořádný disconnect a co přijde po tom, je obejít chybu:

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

Související vlákna:

  • https://sourceware.org/bugzilla/show_bug.cgi?id=13984 může být chyba GDB
  • Odpověď vzdáleného paketu 'g' je příliš dlouhá
  • http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org je jako obvykle skvělým zdrojem těchto problémů
  • 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

Známá omezení:

  • jádro Linuxu nepodporuje (a ani se nezkompiluje bez oprav) s -O0 :Jak de-optimalizovat linuxové jádro a zkompilovat jej s -O0?
  • GDB 7.11 vám při některých typech dokončování karet vybije paměť, a to i po max-completions oprava:Přerušení dokončování tabulátoru pro velké binární soubory Pravděpodobně nějaké rohové pouzdro, které nebylo pokryto v tomto patchi. Takže ulimit -Sv 500000 je moudrá akce před laděním. Vybuchlo konkrétně, když jsem dokončil kartu file<tab> pro filename argument sys_execve jako na:https://stackoverflow.com/a/42290593/895245

Viz také:

  • https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst oficiální "dokumentace" linuxového jádra
  • Linuxové jádro živé ladění, jak se to provádí a jaké nástroje se používají?

Odpověď BjoernID pro mě opravdu nefungovala. Po prvním pokračování není dosaženo bodu přerušení a při přerušení bych viděl řádky jako:

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

Myslím, že to má něco společného s různými režimy CPU (reálný režim v BIOSu vs. dlouhý režim, když se Linux nabootoval). Řešením je každopádně nejprve spustit QEMU bez čekání (tj. bez -S ):

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

V mém případě jsem potřeboval během bootování něco zlomit, takže po několika decisekundách jsem spustil příkaz gdb. Pokud máte více času (např. potřebujete ladit modul, který se načítá ručně), pak na načasování opravdu nezáleží.

gdb umožňuje zadat příkazy, které se mají spustit při spuštění. Tím je automatizace o něco jednodušší. Chcete-li se připojit ke QEMU (která by již měla být spuštěna), přerušit funkci a pokračovat ve vykonávání, použijte:

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

Linux
  1. Sledujte příkazy a úkoly pomocí příkazu watch v systému Linux

  2. Linux – Jak linuxové jádro zná hlavní a vedlejší čísla zařízení?

  3. Ladění linuxového jádra pomocí QEMU

  1. Analyzujte linuxové jádro pomocí ftrace

  2. Jak ladit programy C v Linuxu pomocí gdb

  3. Flatpak na Linuxu:Co to je a jak s ním instalovat aplikace

  1. Jak vytvořit alias a používat příkaz Alias ​​v Linuxu

  2. Jak zkontrolovat verzi OS a Linuxu

  3. Jak zachytit terminálové relace a výstup pomocí příkazu skriptu Linux