linux linux-kernel gdb qemu

¿Cómo depurar el kernel de Linux con GDB y QEMU?



linux-kernel (5)

Cuando intentas iniciar vmlinux exe usando gdb, lo primero que hace gdb es emitir cmds:

(gdb) target localhost local: 1234

(gdb) rompe start_kernel

(continuar)

Esto romperá el kernel en start_kernel.

Soy nuevo en el desarrollo del kernel y me gustaría saber cómo ejecutar / depurar el kernel de Linux utilizando QEMU y gdb. De hecho, estoy leyendo el libro de Robert Love, pero desafortunadamente no ayuda al lector sobre cómo instalar las herramientas adecuadas para ejecutar o depurar el kernel ... Entonces, lo que hice fue seguir este tutorial http://opensourceforu.efytimes.com/2011/02/kernel-development-debugging-using-eclipse/ . Estoy usando eclipse como un IDE para desarrollar en el kernel, pero primero quería que funcione en QEMU / gdb. Entonces, lo que hice hasta ahora fue:

1) Para compilar el kernel con:

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

2) Una vez que la compilación termina, ejecuto Qemu usando:

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

que lanzan el kernel en estado "detenido"

3) Por lo tanto, tengo que usar gdb, intento el siguiente comando:

gdb ./vmlinux

que lo ejecuta correctamente pero ... Ahora no sé qué hacer ... Sé que tengo que usar la depuración remota en el puerto 1234 (puerto predeterminado utilizado por Qemu), usando vmlinux como el archivo de tabla de símbolos para depuración

Entonces mi pregunta es: ¿qué debo hacer para ejecutar kernel en Qemu, adjuntar mi depurador y así lograr que funcionen juntos para facilitar mi vida con el desarrollo del kernel?



La respuesta de BjoernID realmente no funcionó para mí. Después de la primera continuación, no se alcanza ningún punto de interrupción y en la interrupción, veo líneas como:

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

Supongo que esto tiene algo que ver con diferentes modos de CPU (modo real en BIOS vs. modo largo cuando Linux arranca). De todos modos, la solución es ejecutar QEMU primero sin esperar (es decir, sin -S ):

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

En mi caso, tuve que interrumpir algo durante el arranque, así que después de algunos decisegundos, ejecuté el comando gdb. Si tiene más tiempo (por ejemplo, necesita depurar un módulo que se carga manualmente), entonces el tiempo realmente no importa.

gdb permite especificar comandos que deben ejecutarse cuando se inician. Esto hace que la automatización sea un poco más fácil. Para conectarse a QEMU (que ya debería haberse iniciado), interrumpir una función y continuar la ejecución, use:

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


Lo intentaría:

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

El uso de la opción ''-s'' hace que qemu escuche en el puerto tcp :: 1234, al que puede conectarse como localhost: 1234 si está en la misma máquina. La opción ''-S'' de Qemu hace que Qemu detenga la ejecución hasta que usted dé el comando de continuar.

Lo mejor probablemente sea echar un vistazo a un tutorial decente de GDB para llevarse bien con lo que está haciendo. Este se ve bastante bien.


Procedimiento paso a paso probado en el host Ubuntu 16.10

Para empezar desde cero rápidamente, he realizado un ejemplo mínimo de QEMU + Buildroot completamente automatizado en: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md los pasos están cubiertos a continuación.

Primero obtenga un sistema de archivos raíz rootfs.cpio.gz . Si necesita uno, considere:

Luego en el kernel de 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

En otra terminal, desde el interior del árbol del kernel de Linux, supongamos que desea iniciar la depuración desde 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''

y hemos terminado!

Para ver los módulos del kernel, consulte: ¿Cómo depurar los módulos del kernel de Linux con QEMU?

Para Ubuntu 14.04, GDB 7.7.1, se necesitaba hbreak , se ignoraron los breakpoints del software break . Ya no es el caso en 16.10. Ver también: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

La disconnect desordenada y lo que viene después son para evitar el error:

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

Temas relacionados:

Limitaciones conocidas

  • el kernel de Linux no es compatible (y ni siquiera compila sin parches) con -O0 : ¿cómo optimizar el kernel de Linux y compilarlo con -O0?
  • GDB 7.11 hará estallar su memoria en algunos tipos de finalización de pestañas, incluso después de la corrección de max-completions : Interrupción de finalización de pestañas para binarios grandes Probablemente algún caso de esquina que no estaba cubierto en ese parche. Entonces, un ulimit -Sv 500000 es una acción inteligente antes de la depuración. Sopló específicamente cuando sys_execve file<tab> para el argumento de filename de filename de sys_execve como en: https://.com/a/42290593/895245

Ver también: